Господа, подскажите по C++ касательно конструктора Есть рабочий код
{
const VFPguard g;
other_code();
}
В данном случае используется принцип RAII (захват ресурса есть инициализация), переменная g хранит в себе контекст VFPv3-D16:
extern "C" void vPortSaveVFP(VFPguard *s);
extern "C" void vPortRestoreVFP(VFPguard *s);
struct VFPguard {
private:
struct {
uint64_t d[16];
uint32_t s;
} d;
public:
VFPguard() {vPortSaveVFP(this);}
~VFPguard() {vPortRestoreVFP(this);}
};
Ну и сами функции сохранения контекста:
.syntax unified
.cpu cortex-r4
.fpu vfpv3-d16
.text
.arm
.section .text, "ax"
.global vPortSaveVFP
.global vPortRestoreVFP
/* Сохранение контекста VFP в указанном месте */
.func vPortSaveVFP
.type vPortSaveVFP, "function"
vPortSaveVFP:
VSTM R0!, {D0-D15}
VMRS R1, FPSCR
STR R1, [R0]
bx lr
.size vPortSaveVFP, . - vPortSaveVFP
.endfunc
/* Восстановление контекста VFP из указанного места */
.func vPortRestoreVFP
.type vPortRestoreVFP, "function"
vPortRestoreVFP:
VLDM R0!, {D0-D15}
LDR R0, [R0]
VMSR FPSCR, R0
bx lr
.size vPortRestoreVFP, . - vPortRestoreVFP
.endfunc
.end
Компилятор gcc справедливо ругается на тот факт, что нет инициализации переменных класса:
src/irq.cpp: In constructor 'VFPguard::VFPguard()':
src/irq.cpp:42:1: warning: 'VFPguard::d' should be initialized in the member initialization list [-Weffc++]
VFPguard::VFPguard() {vPortSaveVFP(this);}
Однако, если я конструктор напишу подобным образом VFPguard::VFPguard() : d() {vPortSaveVFP(this);} то компилятор будет удовлетворён и вставит вызов memset для инициализации 0 всех 132 байт структуры d, что занимает лишних 320 тактов процессора на 200 МГц (видимо, memset из newlib неоптимально написана). Вызов абсолютно бесполезный, потому что в функции vPortSaveVFP() будет сразу же переписано содержимое структуры d.
Если же я напишу VFPguard::VFPguard() : d() {vPortSaveVFP(this);} и изменю структуру d нижепоказанным образом, то компилятор продолжает быть удовлетворённым и всё равно обнуляет переменную d.s (ненужная операция).
extern "C" void vPortSaveVFP(VFPguard *s);
extern "C" void vPortRestoreVFP(VFPguard *s);
struct VFPguard {
private:
struct regs {
uint64_t d[16];
uint32_t s;
regs() : s() {}
} d;
public:
VFPguard() : d() {vPortSaveVFP(this);}
~VFPguard() {vPortRestoreVFP(this);}
};
Как заставить компилятор компилировать без предупреждений (кроме отключения флага -Weffc++) ?
Вот такой код с магическими числами делает то что надо
struct VFPguard {
private:
uint32_t regs[16 * 2 + 1];
public:
VFPguard() {vPortSaveVFP(this);}
~VFPguard(){vPortRestoreVFP(this);}
};
Других вариантов нет?