<bgdev />free

Вход Регистрация

Смислено приложение на АИ-то?
0

0 1 2 3 4 ...10 11 12 13 14 ...22 23 24 25 26

#135964 (ツ) waldorf
Създадено на 21.02.2025 , видяно: 307 пъти.
Дон Реба

добре де, но ти твърдиш че той точно това не прави - подаваш му обектен файл и той не търси в него. ще ме накараш да го пробвам

Тц. Добавям му библиотеки. И в тези библиотеки има файлове само със статични функции които си закачат евънт хандлърите през тези линкерски секции с които става магията. И за да е гарантирано, че ще се линкнат трябва да ходя да ги маркирам всички в cmake с whole-archive - иначе не се линкват и колегите като напишат някой евънт хендлър се чудят що не работи. Алтернативата е да пишат инит функции и в тези инит функции да се закачат хендлърите за евънтите - ама така не ме кефи щото се генерира един излишен код за инициализация в началото и гледам да го орежа с по тарикатско линкване.

#135965 (ツ) waldorf
Създадено на 21.02.2025 , видяно: 304 пъти.
Дон Реба

пробвах го, правя чист файл съсследното:


#include "apm32f051.h"

void USART1_IRQHandler(void){
	u8 c=USART1->RXDATA;
	USART1->TXDATA=c;
}

просто ехо от серийния, по прекъсване

нищо друго няма, линквам си това дето го човъркам към обектния и работи както се очаква - връща ехо от серийния

32f051? Аз мъча един 32L031 ... мамицата му ...

#135966 (ツ) Дон Реба
Създадено на 21.02.2025 , видяно: 303 пъти.

добре де, а щом са статични КАК успяваш да ги извикаш отвън?

#135968 (ツ) waldorf
Създадено на 21.02.2025 , видяно: 301 пъти.

Лесно. Адресите на функциите отиват в една специална линкерска секция. И после като стане някакъв евънт се обхождат всички записи в тази секция и се вика за този евънт ако има някакъв хендлъри.

#135969 (ツ) waldorf
Създадено на 21.02.2025 , видяно: 299 пъти.

Конфигурацията на линкера:

SECTIONS
{
    .events :
    {
        __events_start = .;
        KEEP(*(SORT(.events*)));
        __events_end = .;
    }

    .event_handlers :
    {
        __event_handlers_start = .;
        KEEP(*(SORT(.event_handlers*)));
        __event_handlers_end = .;
    }
}
# Keep INSERT AFTER to append this linker script to the default one.
# See https://www.sourceware.org/binutils/docs/ld/Miscellaneous-Commands.
INSERT AFTER .text;

Хедър файла на евънта:

#define EVENTS_SECTION         ".events"
#define EVENTS_HANDLER_SECTION ".event_handlers"

#define __EVENT_DECLARE(_type, _event, _value_t, _value, _default, _set, _get) \
                                                                               \
    typedef _type _value_t;                                                    \
                                                                               \
    extern _value_t _value;                                                    \
    extern _value_t _default;                                                  \
                                                                               \
    extern event_t _event;                                                     \
                                                                               \
    static inline void _set(_type value)                                       \
    {                                                                          \
        _type old = _value;                                                    \
        _value = value;                                                        \
        event_notify(&_event, &old, &value);                                   \
    }                                                                          \
                                                                               \
    static inline _type _get(void)                                             \
    {                                                                          \
        return _value;                                                         \
    }

#define _EVENT_DECLARE(_name, _type)   \
    __EVENT_DECLARE(                   \
        _type,                         \
        CONCAT_N(__, _name, _event),   \
        CONCAT_N(__, _name, _value_t), \
        CONCAT_N(__, _name, _value),   \
        CONCAT_N(__, _name, _default), \
        CONCAT_N(_name, _set),         \
        CONCAT_N(_name, _get))

#define __EVENT_IMPLEMENT(_name, _type, _default_value, _persistent, _event, _value_t, _value, _default) \
                                                                                                         \
    _value_t _value = _default_value;                                                                    \
    _value_t _default = _default_value;                                                                  \
                                                                                                         \
    event_t _event __attribute__((section(EVENTS_SECTION))) = {                                          \
        .name = #_name,                                                                                  \
        .value = &_value,                                                                                \
        .default_value = &_default,                                                                      \
        .size = sizeof(_value),                                                                          \
        .is_persistent = _persistent                                                                     \
    };

#define _EVENT_IMPLEMENT(_name, _type, _default_value, _persistent) \
    __EVENT_IMPLEMENT(                                              \
        _name,                                                      \
        _type,                                                      \
        _default_value,                                             \
        _persistent,                                                \
        CONCAT_N(__, _name, _event),                                \
        CONCAT_N(__, _name, _value_t),                              \
        CONCAT_N(__, _name, _value),                                \
        CONCAT_N(__, _name, _default))


#define __EVENT_SUBSCRIBE(_event, _handler, _wrapper, _list, _value_t)                   \
    static void _wrapper(const void* const old_value, const void* const new_value)       \
    {                                                                                    \
        _handler((const _value_t* const)old_value, (const _value_t* const)new_value);    \
    }                                                                                    \
                                                                                         \
    event_handler_t _list __attribute__((__used__, section(EVENTS_HANDLER_SECTION))) = { \
        .event = &_event,                                                                \
        .handler = _wrapper                                                              \
    }

#define _EVENT_SUBSCRIBE(_name, _handler)         \
    __EVENT_SUBSCRIBE(                            \
        CONCAT_N(__, _name, _event),              \
        _handler,                                 \
        CONCAT_N(__, _name, _wrapper_, __LINE__), \
        CONCAT_N(__, _name, _list_, __LINE__),    \
        CONCAT_N(__, _name, _value_t))

Имплементация за всички евънти:

void event_notify(const event_t* const event, const void* const old_value, const void* const new_value)
{
    if (!notifications_enabled)
        return;

    if (event->is_persistent)
    {
        /* Take a copy of the handler to avoid NULL pointer assignment from another thread */
        void (*persistent_handler_copy)(const event_t* const event, const void* const value) = persistent_handler;

        if (persistent_handler_copy != NULL)
            persistent_handler_copy(event, new_value);
    }

    BP_LOG_DEBUG("Looking for handlers for %s", event->name);

    /* cppcheck-suppress comparePointers */
    for (const event_handler_t* event_handler = __event_handlers_start; event_handler < __event_handlers_end; event_handler++)
    {
        BP_LOG_DEBUG("Calling handler %s", event->name);

        if (event_handler->event == event)
            event_handler->handler(old_value, new_value);
    }
}

И употреба:

Дефинираш си евънт някъде в хедър файл.

EVENT_DECLARE(system_tick_second, uint32_t);

В Ц файл правиш имплементация.

EVENT_IMPLEMENT(system_tick_second, uint32_t, 0);

Закачване на хендлър:

void pid_second_tick_callback(const uint32_t* const old, const uint32_t* const new)
{
...
}

EVENT_SUBSCRIBE(system_tick_second, pid_second_tick_callback);

Нотификация при нов евънт:

    system_tick_second_set(sys_ticks++);
#135971 (ツ) Дон Реба
Създадено на 21.02.2025 , видяно: 294 пъти.

мен ми звучи като да си се преебал от много знания, аз като нищо не знам просто си пиша функцията с името което е зачукано в таблицата и нямам такива грижи. тия цимейкове, линкерскриптове и тн са ми черна магия

#135972 (ツ) Последният акаунт на Единия
Създадено на 21.02.2025 , видяно: 289 пъти.
Дон Реба

мен ми звучи като да си се преебал от много знания, аз като нищо не знам просто си пиша функцията с името което е зачукано в таблицата и нямам такива грижи. тия цимейкове, линкерскриптове и тн са ми черна магия

Негър... :-(

#135973 (ツ) |
Създадено на 21.02.2025 , видяно: 273 пъти.
waldorf

А за LTS - тука нещата са малко по сложни. По точно е да се каже, че това всъщност е отложена компилация която се изпълнява по време на линкване когато вече е ясно какво ще влезе и какво не в крайния файл. Това позволява да се правят cross border оптимизации които компилатора иначе не може да направи защото е ограничен до един .c/.o файл. И чак накра имаме финално линкване. Абе вуду магия е.

Не е чак вуду магия, просто compiler backend дейностите се правят след като се resolve-нат символите. Фронтенд-а на компилатора така или иначе генерира някакво междинно представяне на кода (IR / intermediate representation в LLVM), линкера го взима, resolve symbols, backend optimizations, emit machine code.

Честно казано не знам колко полза има от това, понеже ние всички сме свикнали как да правим така, че обектните файлове да нямат много неща, които да се линкнат и да не се използват. Май най-голямата полза е от това, че може да inline функции по време на свързване.

#136001 (ツ) waldorf
Създадено на 21.02.2025 , видяно: 247 пъти.
|

Не е чак вуду магия, просто compiler backend дейностите се правят след като се resolve-нат символите. Фронтенд-а на компилатора така или иначе генерира някакво междинно представяне на кода (IR / intermediate representation в LLVM), линкера го взима, resolve symbols, backend optimizations, emit machine code.

Честно казано не знам колко полза има от това, понеже ние всички сме свикнали как да правим така, че обектните файлове да нямат много неща, които да се линкнат и да не се използват. Май най-голямата полза е от това, че може да inline функции по време на свързване.

Нямам идея и аз. Имам някакъв смътен спомен, че преди време бях чел анализите на един юнак който правеше оптимизации за някой от браузърите - май беше фирефокс. И той беше писал за ползата от файдата за ЛТО - колко утежнява компилация и линкване и съответно как се отразява на крайния резултат. Имаше файда ама не беше нещо фрапиращо.

Но то за голям проект май няма и как да има файда. Но виж за малък като фирмуер за микроконтролер по може да има.

#136002 (ツ) waldorf
Създадено на 21.02.2025 , видяно: 245 пъти.
Дон Реба

мен ми звучи като да си се преебал от много знания, аз като нищо не знам просто си пиша функцията с името което е зачукано в таблицата и нямам такива грижи. тия цимейкове, линкерскриптове и тн са ми черна магия

Тц. Всъщност това оправи много проблеми и опрости сорса. Абе мързи ме да пиша, напомни ми като се видим на живо някой път да я разчекнем темата, интересно е и има полза.

#136017 (ツ) |
Създадено на 22.02.2025 , видяно: 226 пъти.
waldorf

Нямам идея и аз. Имам някакъв смътен спомен, че преди време бях чел анализите на един юнак който правеше оптимизации за някой от браузърите - май беше фирефокс. И той беше писал за ползата от файдата за ЛТО - колко утежнява компилация и линкване и съответно как се отразява на крайния резултат. Имаше файда ама не беше нещо фрапиращо.

Но то за голям проект май няма и как да има файда. Но виж за малък като фирмуер за микроконтролер по може да има.

От това което се сещам в момента, най-полезни са автоматичните inline без да се налага инлайн функциите да са в хедър файловете и че могат да се пропуска запазването на caller-saved регистри ако функциите, които се викат са tail-call. Сигурно има и други.

#136018 (ツ) Дон Реба
Създадено на 22.02.2025 , видяно: 221 пъти.
|

Не очаквах да не знаеш как работи линкъра.

техническа литература спрях да чета 9ти клас, като ползвам някакъв инструмент постепенно ми се оформя някакъв модел как работи, което не е задължително да е реално така. щом казваш че линкера не ползва входната точка за старт вярвам ти, ти си читанка, сигурно е така както казваш. още повече че линкера наистина не знае къде свършват функциите, всъщност дори не знае кое е фукция, в това съм се убедил и аз. и все пак неизползвания код някак изчезва, и това го прави точно линкера, ако не е по начина който аз предполагах значи има някакъв постпроцес, който прави същото (сигурно това ЛТО), но след като вече си изхабил квадратично време за търсене на всеки срещу всеки.

#136024 (ツ) |
Създадено на 22.02.2025 , видяно: 195 пъти.
Дон Реба

техническа литература спрях да чета 9ти клас, като ползвам някакъв инструмент постепенно ми се оформя някакъв модел как работи, което не е задължително да е реално така. щом казваш че линкера не ползва входната точка за старт вярвам ти, ти си читанка, сигурно е така както казваш. още повече че линкера наистина не знае къде свършват функциите, всъщност дори не знае кое е фукция, в това съм се убедил и аз. и все пак неизползвания код някак изчезва, и това го прави точно линкера, ако не е по начина който аз предполагах значи има някакъв постпроцес, който прави същото (сигурно това ЛТО), но след като вече си изхабил квадратично време за търсене на всеки срещу всеки.

Никога не съм чел нищо за линкъри, просто съм ги използвал повече и за по-разнообразни неща от теб. Можеш много лесно да се убедиш, че функциите НЕ изчезват. Сложи две функции (не static) в един файл, компилирай го и използвай само едната в проекта си. После накарай дебъгера да ти дисасемблира другата по име.

#136042 (ツ) waldorf
Създадено на 22.02.2025 , видяно: 163 пъти.
Дон Реба

техническа литература спрях да чета 9ти клас, като ползвам някакъв инструмент постепенно ми се оформя някакъв модел как работи, което не е задължително да е реално така. щом казваш че линкера не ползва входната точка за старт вярвам ти, ти си читанка, сигурно е така както казваш. още повече че линкера наистина не знае къде свършват функциите, всъщност дори не знае кое е фукция, в това съм се убедил и аз. и все пак неизползвания код някак изчезва, и това го прави точно линкера, ако не е по начина който аз предполагах значи има някакъв постпроцес, който прави същото (сигурно това ЛТО), но след като вече си изхабил квадратично време за търсене на всеки срещу всеки.

Кода обикновено се реже по време на компилация. При линкване не се пипа. А ЛТО май по подразбиране е изключено и то наистина е направено точно за да се правят такива оптимизации.

#136072 (ツ) |
Създадено на 22.02.2025 , видяно: 143 пъти.
waldorf

Кода обикновено се реже по време на компилация. При линкване не се пипа. А ЛТО май по подразбиране е изключено и то наистина е направено точно за да се правят такива оптимизации.

Използването на LTO не е много лесно. Аз съм го правил с LLVM, не помня защо. Вместо до .о трябва д компилираш до byte ode (.bc файлове) и после да ги линкваш тях.

#136073 (ツ) waldorf
Създадено на 22.02.2025 , видяно: 140 пъти.

Що ли си мисля, че сега всичко е в .o файла. Иначе ще е супер тегаво за Makefile-овете.

#136080 (ツ) Дон Реба
Последно редактирано на 23.02.2025 от Дон Реба, видяно: 125 пъти.
waldorf

Кода обикновено се реже по време на компилация. При линкване не се пипа.

абсолютно твърдо не, и това вече не е до знаене как работи линкера, просто го виждам с очите си че кода дето е в обектните файлове го няма в бина. рязането при компилация е само оптимизация, реже се абсолютно недостъпния (според компилатора) код. това обаче не значи код до който няма път в текущия файл, всяка функция може да бъде извикана отвън. с това и започнахме изобщо приказките по тая тема - че компилатора ми отраза статични функции, което е чист бъг "преписан" от С компилатора - там не е бъг защото са наистина недостъпни отвън, но в С++ е бъг защото са достъпни. това обаче няма нищо общо с Голямото Рязане, което се прави от линкера. впрочем ето го линкерския ред , аз от заклинания не разбирам и не знам има ли пуснато лто



%COMPILER_PATH%ld.exe --sysroot=..\arm\bin -X -o bootldr.elf  ./lib/bootldr.o   --gc-sections -Map .\bootldr.map --cref --check-sections --gc-sections --entry=entry --unresolved-symbols=report-all --warn-common --warn-section-align  -T ../arm/gcc_APM32F05xx8.ld
#136081 (ツ) Дон Реба
Последно редактирано на 23.02.2025 от Дон Реба, видяно: 121 пъти.

проверих го сега за да се убедя че не реже на ниво обектен файл, а на ниво функция. бутлодера е подходящ за целта, него принципно не го линквам а директно с objcopy го превръщам от о в бин и тоя бин го забивам в последния сектор на флаша. пуснах го да мине през линкера (виж реда в горния пост) - бинката нарастна 16 байта, от 680 на 696. закоментирах обаче един ред в него където се вика тлъста функция - objcopy не се впечатли, размера си остана 680 (дори не спадна, явно се закръгля на нещо). с линкера обаче бинката спадна драстично - линкера изряза неизползваната функция. компилатора не я закача, всъщност компилатора не знае коя е входната точка, но линкера ако не му кажа отказва да работи, т.е. "работи" но генерира празен файл.

#136085 (ツ) waldorf
Създадено на 23.02.2025 , видяно: 106 пъти.

Хм. Може и да си прав. Трябва да погледна.

#136110 (ツ) |
Създадено на 23.02.2025 , видяно: 82 пъти.
Дон Реба

абсолютно твърдо не, и това вече не е до знаене как работи линкера, просто го виждам с очите си че кода дето е в обектните файлове го няма в бина. рязането при компилация е само оптимизация, реже се абсолютно недостъпния (според компилатора) код. това обаче не значи код до който няма път в текущия файл, всяка функция може да бъде извикана отвън. с това и започнахме изобщо приказките по тая тема - че компилатора ми отраза статични функции, което е чист бъг "преписан" от С компилатора - там не е бъг защото са наистина недостъпни отвън, но в С++ е бъг защото са достъпни. това обаче няма нищо общо с Голямото Рязане, което се прави от линкера. впрочем ето го линкерския ред , аз от заклинания не разбирам и не знам има ли пуснато лто



%COMPILER_PATH%ld.exe --sysroot=..\arm\bin -X -o bootldr.elf  ./lib/bootldr.o   --gc-sections -Map .\bootldr.map --cref --check-sections --gc-sections --entry=entry --unresolved-symbols=report-all --warn-common --warn-section-align  -T ../arm/gcc_APM32F05xx8.ld

Имаш ли - ffunction-sections като компилираш? Защото това ти отделя всяка функция в отделна секция, реално отделен object file от гледна точка на компилатора.

0 1 2 3 4 ...10 11 12 13 14 ...22 23 24 25 26

Смислено приложение на АИ-то?
0

AsmBB v3.0 (check-in: 7544654b24928b93); SQLite v3.47.0 (check-in: 03a9703e27c44437);
©2016..2024 John Found; Licensed under EUPL. Powered by Assembly language Created with Fresh IDE