SlideShare a Scribd company logo
1 of 60
Кодогенерация C++
кроссплатформенно
часть 2
Алексей Ткаченко, ОАО “Пеленг”
tkachenko@peleng.by
alexey.tkachenko@gmail.com
О чём доклад?
● сопоставление языковых конструкций C++ с генерируемым
машинным кодом
● сравнение генерации для различных платформ и архитектур
● особенности архитектур в контексте кроссплатформенности
● развенчание мифов
2
Исходный код
Исходный код
Фазы компиляции
3
Лексический
анализ
Синтаксический
анализ
Семантический
анализ
Оптимизация Кодогенерация
Исходный код
Исходный код
Исполняемая
программа
Платформы
Рассмотрим
● Intel x86 (CISC, 32bit) / MSVS 2015 (Windows 10)
● x86-64 (CISC, 64bit) / MSVS 2015 (Windows 10)
● ARM Cortex-A7 (RISC, 32bit) / GCC 4.6.3 (Debian 7 @ CubieBoard2)
● Atmel AVR (AVR RISC, 8bit) / GCC 4.8.1, Arduino (Windows 10)
● IBM PowerPC (RISC, 32bit) / Xilinx EDK 14.7 (Ubuntu 17)
● Xilinx Microblaze (RISC, 32bit, over FPGA) / Xilinx EDK 14.7 (Ubuntu 17)
4
Вызов метода
C++
class BaseClass
{
ptrdiff_t Method1(ptrdiff_t a);
ptrdiff_t Method2(ptrdiff_t a) const;
BaseClass operator~();
virtual ptrdiff_t Method3(ptrdiff_t
a);
}
BaseClass* obj = new BaseClass();
ptrdiff_t result = obj->Method1(1) + 1;
x86
push 1
mov ecx,esi ; this
call ?Method1@BaseClass@@QAEHH@Z
mov edi,eax
x64
mov edx,1
mov rcx,rbx
call ?Method1@BaseClass@@QEAA_J_J@Z
mov rdi,rax
5
Вызов метода
C++
class BaseClass
{
ptrdiff_t Method1(ptrdiff_t a);
ptrdiff_t Method2(ptrdiff_t a) const;
BaseClass operator~();
virtual ptrdiff_t Method3(ptrdiff_t
a);
}
BaseClass* obj = new BaseClass();
ptrdiff_t result = obj->Method1(1) + 1;
6
AVR
ldi r22, 0x01 ; 1
ldi r23, 0x00 ; 0
movw r24, r28
call <BaseClass::Method1(int)>
movw r16, r24
ARM
mov r0, r4
movs r1, #1
bl <BaseClass::Method1(int)>
adds r5, r0, #1
Вызов метода
C++
class BaseClass
{
ptrdiff_t Method1(ptrdiff_t a);
ptrdiff_t Method2(ptrdiff_t a) const;
BaseClass operator~();
virtual ptrdiff_t Method3(ptrdiff_t
a);
}
BaseClass* obj = new BaseClass();
ptrdiff_t result = obj->Method1(1) + 1;
7
PowerPC
mr r3,r31
li r4,1
bl BaseClass::Method1(int)
addi r3,r29,1
MicroBlaze
addk r19, r3, r0
addk r5, r19, r0
brlid r15, BaseClass::Method1(int)
addik r6, r0, 1
Вызов константного метода
C++
class BaseClass
{
ptrdiff_t Method1(ptrdiff_t a);
ptrdiff_t Method2(ptrdiff_t a) const;
BaseClass operator~();
virtual ptrdiff_t Method3(ptrdiff_t
a);
}
BaseClass* obj = new BaseClass();
ptrdiff_t result = obj->Method2(2) + 2;
x86
push 2
mov ecx,esi
call ?Method2@BaseClass@@QBEHH@Z
add eax, 2
x64
mov edx,2
mov rcx,rbx
call ?Method2@BaseClass@@QEBA_J_J@Z
add rax, 2
8
Вызов константного метода
C++
class BaseClass
{
ptrdiff_t Method1(ptrdiff_t a);
ptrdiff_t Method2(ptrdiff_t a) const;
BaseClass operator~();
virtual ptrdiff_t Method3(ptrdiff_t
a);
}
BaseClass* obj = new BaseClass();
ptrdiff_t result = obj->Method2(2) + 2;
9
AVR
movw r24, r28
call <BaseClass::Method2(int) const>
movw r16, r24
subi r16, 0xFE
sbci r17, 0xFF
ARM
mov r0, r4
movs r1, #2
bl <BaseClass::Method2(int) const>
adds r5, r0, #2
Вызов константного метода
C++
class BaseClass
{
ptrdiff_t Method1(ptrdiff_t a);
ptrdiff_t Method2(ptrdiff_t a) const;
BaseClass operator~();
virtual ptrdiff_t Method3(ptrdiff_t
a);
}
BaseClass* obj = new BaseClass();
ptrdiff_t result = obj->Method2(2) + 2;
10
PowerPC
mr r3,r31
li r4,2
bl <BaseClass::Method2(int) const>
addi r3,r29,2
MicroBlaze
addk r19, r3, r0
addk r5, r19, r0
brlid r15, <BaseClass::Method2(int) const>
addik r22, r3, 2
Вызов оператора
C++
class BaseClass
{
ptrdiff_t Method1(ptrdiff_t a);
ptrdiff_t Method2(ptrdiff_t a) const;
BaseClass operator~();
virtual ptrdiff_t Method3(ptrdiff_t
a);
}
BaseClass* obj = new BaseClass();
BaseClass op = ~*obj;
x86
mov ecx,esi
call ??SBaseClass@@QAE?AV0@XZ
x64
mov rcx,rbx
call ??SBaseClass@@QEAA?AV0@XZ
11
Вызов оператора
C++
class BaseClass
{
ptrdiff_t Method1(ptrdiff_t a);
ptrdiff_t Method2(ptrdiff_t a) const;
BaseClass operator~();
virtual ptrdiff_t Method3(ptrdiff_t
a);
}
BaseClass* obj = new BaseClass();
BaseClass op = ~*obj;
12
AVR
movw r22, r16
movw r24, r28
adiw r24, 0x01
call <BaseClass::operator~()>
ARM
mov r1, r4
bl <BaseClass::operator~()>
Вызов оператора
C++
class BaseClass
{
ptrdiff_t Method1(ptrdiff_t a);
ptrdiff_t Method2(ptrdiff_t a) const;
BaseClass operator~();
virtual ptrdiff_t Method3(ptrdiff_t
a);
}
BaseClass* obj = new BaseClass();
ptrdiff_t result = ~*obj;
13
PowerPC
mr r3,r31
bl <BaseClass::operator~()>
MicroBlaze
addk r19, r3, r0
addk r6, r19, r0
brlid r15, <BaseClass::operator~()>
Вызов конструктора
C++
class BaseClass
{
protected:
ptrdiff_t x;
ptrdiff_t y;
ptrdiff_t z;
public:
BaseClass();
virtual ~BaseClass();
};
BaseClass::BaseClass()
: x(), y(), z()
{}
x86
mov dword ptr [ecx],offset ??_7BaseClass@@6B@
mov eax,ecx
mov dword ptr [ecx+4],0
mov dword ptr [ecx+8],0
mov dword ptr [ecx+0Ch],0
ret
x64
lea rax,[??_7BaseClass@@6B@]
mov qword ptr [rcx],rax
xor eax,eax
mov qword ptr [rcx+8],rax
mov qword ptr [rcx+10h],rax
mov qword ptr [rcx+18h],rax
mov rax,rcx
ret
14
Вызов конструктора
C++
class BaseClass
{
protected:
ptrdiff_t x;
ptrdiff_t y;
ptrdiff_t z;
public:
BaseClass();
virtual ~BaseClass();
};
BaseClass::BaseClass()
: x(), y(), z()
{}
15
ARM
ldr r2, [pc, #12] ; @VPTR
movs r3, #0
str r3, [r0, #4]
str r3, [r0, #8]
str r2, [r0, #0]
str r3, [r0, #12]
bx lr
nop
@VPTR: .word 0x00009f60
Вызов конструктора
C++
class BaseClass
{
protected:
ptrdiff_t x;
ptrdiff_t y;
ptrdiff_t z;
public:
BaseClass();
virtual ~BaseClass();
};
BaseClass::BaseClass()
: x(), y(), z()
{}
16
PowerPC
lis r9,5
li r0,0
addi r9,r9,0xCDE8
stw r0,12(r3)
stw r9,0(r3)
stw r0,4(r3)
stw r0,8(r3)
blr
MicroBlaze
imm 0x9008
addik r3, r0, 0x45E4
swi r0, r5, 4
swi r0, r5, 8
swi r3, r5, 0
rtsd r15, 8
swi r0, r5, 12
Виртуальные методы: диспетчеризация
17
Base
~Base()
Base::VirtualA()
Base::VirtualB()
vtable
Derived
~
VirtualA
VirtualB
vtable
~
VirtualA
VirtualB
~Derived()
Derived::VirtualA()
Base
Derived
Вызов виртуального метода
C++
class BaseClass
{
ptrdiff_t Method1(ptrdiff_t a);
ptrdiff_t Method2(ptrdiff_t a) const;
BaseClass operator~();
virtual ptrdiff_t Method3(ptrdiff_t
a);
}
BaseClass* obj = new BaseClass();
ptrdiff_t result = obj->Method3(3) + 3;
x86
mov edi,eax
mov eax,dword ptr [edi]
mov ecx,edi
push 3
call dword ptr [eax+4]
x64
mov rdi,rax
mov rax,qword ptr [rdi]
mov edx,3
mov rcx,rdi
call qword ptr [rax+8]
18
Вызов виртуального метода
C++
class BaseClass
{
ptrdiff_t Method1(ptrdiff_t a);
ptrdiff_t Method2(ptrdiff_t a) const;
BaseClass operator~();
virtual ptrdiff_t Method3(ptrdiff_t
a);
}
BaseClass* obj = new BaseClass();
ptrdiff_t result = obj->Method3(3) + 3;
19
AVR
ld r30, Y
ldd r31,
Y+1
ldd r0,
Z+4
ldd r31,
Z+5
mov r30, r0
ARM
ldr r3, [r4, #0]
movs r1, #3
mov r0, r4
ldr r3, [r3, #8]
blx r3
ldi r22,
0x03
ldi r23,
0x00
movw r24,
r28
icall
Вызов виртуального метода
C++
class BaseClass
{
ptrdiff_t Method1(ptrdiff_t a);
ptrdiff_t Method2(ptrdiff_t a) const;
BaseClass operator~();
virtual ptrdiff_t Method3(ptrdiff_t
a);
}
BaseClass* obj = new BaseClass();
ptrdiff_t result = obj->Method3(3) + 3;
20
PowerPC
lwz r9,0(r31)
li r4,3
mr r3,r31
lwz r9,8(r9)
mtctr r9
bctrl
MicroBlaze
addk r19, r3, r0
lwi r3, r19, 0
addk r5, r19, r0
lwi r3, r3, 8
brald r15, r3
Вызов перекрытого виртуального метода
C++
class BaseClass
{
virtual ptrdiff_t Method3(ptrdiff_t
a);
}
class DerivedClass : public BaseClass
{
public:
virtual ptrdiff_t Method3(ptrdiff_t
a);
}
BaseClass* obj = new DerivedClass();
ptrdiff_t result = obj->Method3(4) + 4;
x86
mov edi,eax
mov eax,dword ptr [edi]
mov ecx,edi
push 4
call dword ptr [eax+4]
21
x86 (virtual in base class)
mov edi,eax
mov eax,dword ptr [edi]
mov ecx,edi
push 3
call dword ptr [eax+4]
Указатель на поле
C++
class BaseClass
{
ptrdiff_t x;
ptrdiff_t y;
ptrdiff_t z;
public:
typedef ptrdiff_t BaseClass::*
FieldPtr;
FieldPtr GetField(ptrdiff_t ptr);
};
BaseClass* obj = new BaseClass(1, 2,
3);
BaseClass::FieldPtr field = obj-
>GetField(1);
ptrdiff_t value = obj->*field;
x86
push 3
push 2
push 1
mov ecx,eax
call ??0BaseClass@@QAE@HHH@Z
mov esi,eax
jmp 00403090
xor esi,esi
push 1
mov ecx,esi
call ?GetField@BaseClass@@QAEPQ1@HH@Z
mov edi,dword ptr [eax+esi]
22
Указатель на поле
C++
class BaseClass
{
ptrdiff_t x;
ptrdiff_t y;
ptrdiff_t z;
public:
typedef ptrdiff_t BaseClass::*
FieldPtr;
FieldPtr GetField(ptrdiff_t ptr);
};
BaseClass* obj = new BaseClass(1, 2,
3);
BaseClass::FieldPtr field = obj-
>GetField(1);
ptrdiff_t value = obj->*field;
x64
mov edx,1
lea r9d,[rdx+2]
lea r8d,[rdx+1]
mov rcx,rax
call ??0BaseClass@@QEAA@_J00@Z
mov rbx,rax
mov edx,1
mov rcx,rbx
call
?GetField@BaseClass@@QEAAPEQ1@_J_J@Z
movsxd rcx,eax
mov rdi,qword ptr [rcx+rbx]
23
Указатель на поле
C++
class BaseClass
{
ptrdiff_t x;
ptrdiff_t y;
ptrdiff_t z;
public:
typedef ptrdiff_t BaseClass::*
FieldPtr;
FieldPtr GetField(ptrdiff_t ptr);
};
BaseClass* obj = new BaseClass(1, 2,
3);
BaseClass::FieldPtr field = obj-
>GetField(1);
ptrdiff_t value = obj->*field;
24
ARM
movs r1, #1
movs r2, #2
movs r3, #3
mov r4, r0
bl <BaseClass::BaseClass(int, int,
int)>
mov r0, r4
movs r1, #1
bl <BaseClass::GetField(int)>
ldr r5, [r4, r0]
Указатель на поле
C++
class BaseClass
{
ptrdiff_t x;
ptrdiff_t y;
ptrdiff_t z;
public:
typedef ptrdiff_t BaseClass::*
FieldPtr;
FieldPtr GetField(ptrdiff_t ptr);
};
BaseClass* obj = new BaseClass(1, 2,
3);
BaseClass::FieldPtr field = obj-
>GetField(1);
ptrdiff_t value = obj->*field;
25
PowerPC
li r4,1
li r5,2
li r6,3
bl <BaseClass::BaseClass(int, int,
int)>
mr r3,r31
li r4,1
bl <BaseClass::GetField(int)>
lwzx r29,r31,r3
Указатель на поле
C++
class BaseClass
{
ptrdiff_t x;
ptrdiff_t y;
ptrdiff_t z;
public:
typedef ptrdiff_t BaseClass::*
FieldPtr;
FieldPtr GetField(ptrdiff_t ptr);
};
BaseClass* obj = new BaseClass(1, 2,
3);
BaseClass::FieldPtr field = obj-
>GetField(1);
ptrdiff_t value = obj->*field;
26
MicroBlaze
addk r5, r3, r0
addik r6, r0, 1
addik r7, r0, 2
addik r8, r0, 3
imm ...
brlid r15, BaseClass::BaseClass(int, int, int)>
addk r19, r3, r0
addk r5, r19, r0
imm ...
brlid r15, <BaseClass::GetField(int)>
lw r22, r3, r19
Указатель на метод
C++
class BaseClass
{
public:
typedef ptrdiff_t
(BaseClass::*MethodPtr) (ptrdiff_t);
MethodPtr GetMethod(ptrdiff_t);
};
BaseClass* obj = new DerivedClass();
BaseClass::MethodPtr method = obj-
>GetMethod(0);
ptrdiff_t value = (obj->*method)(42) +
1;
x86
push 0
mov ecx,esi
call ?GetMethod@BaseClass@@QAEP81@AEHH@ZH@Z
push 2Ah
mov ecx,esi
call eax
27
Указатель на виртуальный метод
C++
class BaseClass
{
public:
typedef ptrdiff_t
(BaseClass::*MethodPtr) (ptrdiff_t);
MethodPtr GetMethod(ptrdiff_t);
};
BaseClass* obj = new DerivedClass();
BaseClass::MethodPtr method = obj-
>GetMethod(0);
ptrdiff_t value = (obj->*method)(42) +
1;
x86
push 1
mov ecx,esi
call ?GetMethod@BaseClass@@QAEP81@AEHH@ZH@Z
push 2Ah
mov ecx,esi
call eax
mov eax,dword ptr [ecx]
jmp dword ptr [eax+4]
28
Указатель на метод
C++
class BaseClass
{
public:
typedef ptrdiff_t
(BaseClass::*MethodPtr) (ptrdiff_t);
MethodPtr GetMethod(ptrdiff_t);
};
BaseClass* obj = new DerivedClass();
BaseClass::MethodPtr method = obj-
>GetMethod(0);
ptrdiff_t value = (obj->*method)(42) +
1;
x64
mov edx,1
mov rcx,rbx
call ?GetMethod@BaseClass@@QEAAP81@EAA_J_J@Z0@Z
mov edx,2Ah
mov rcx,rbx
call rax
29
Указатель на виртуальный метод
C++
class BaseClass
{
public:
typedef ptrdiff_t
(BaseClass::*MethodPtr) (ptrdiff_t);
MethodPtr GetMethod(ptrdiff_t);
};
BaseClass* obj = new DerivedClass();
BaseClass::MethodPtr method = obj-
>GetMethod(0);
ptrdiff_t value = (obj->*method)(42) +
1;
x64
xor edx,edx
mov rcx,rbx
call ?GetMethod@BaseClass@@QEAAP81@EAA_J_J@Z0@Z
mov edx,2Ah
mov rcx,rbx
call rax
mov rax,qword ptr [rcx]
jmp qword ptr [rax+8]
30
Указатель на метод
31
Callee
Virtual callee
Caller
Trampoline
Указатель на метод
C++
class BaseClass
{
public:
typedef ptrdiff_t
(BaseClass::*MethodPtr) (ptrdiff_t);
MethodPtr GetMethod(ptrdiff_t ptr);
};
BaseClass* obj = new DerivedClass();
BaseClass::MethodPtr method = obj-
>GetMethod(0);
ptrdiff_t value = (obj->*method)(42) +
1;
32
ARM
movs r2, #1
add r0, sp, #16
mov r1, r4
bl BaseClass::GetMethod(int)
ldr r0, [sp, #20]
ldr r3, [sp, #16]
lsls r2, r0, #31
it pl
addpl.w r0, r4, r0, asr #1
bpl.n @1
asrs r2, r0, #1
adds r0, r4, r2
ldr r2, [r4, r2]
ldr r3, [r2, r3]
@1:
movs r1, #42
blx r3
Указатель на метод
C++
class BaseClass
{
public:
typedef ptrdiff_t
(BaseClass::*MethodPtr) (ptrdiff_t);
MethodPtr GetMethod(ptrdiff_t ptr);
};
BaseClass* obj = new DerivedClass();
BaseClass::MethodPtr method = obj-
>GetMethod(0);
ptrdiff_t value = (obj->*method)(42) +
1;
33
PowerPC
mr r3,r31
li r4,1
bl BaseClass::GetMethod(int)
mr r0,r3
add r11,r31,r4
andi. r9,r0,1
beq- @1
lwzx r9,r31,r4
add r9,r9,r0
lwz r0,-1(r9)
@1:
mr r3,r11
li r4,42
mtctr r0
bctrl
Указатель на метод
34
Callee
Virtual callee
vtable
~
VirtualA
VirtualB
Pointer
xxxx xxx1
Pointer
yyyy yyy0
Тривиальные глобальные данные
C++
int Trivial;
Point EmptyPoint;
int Initialized = 42;
Ничего не стоят в процессе выполнения.
Неинициализированные глобальные данные
заполняются нулевыми байтами и не требуют
хранения в загрузочном образе.
Инициализированные данные хранятся в виде
начальных значений в загрузочном образе.
35
Статические переменные функции
C++
int& GetStaticA()
{
static int s;
return s;
}
int& GetStaticB()
{
static int s = 42;
return s;
}
36
x86
mov eax,407544h
ret
mov eax,407040h
ret
x64
lea rax,[140008918h]
ret
lea rax,[14000807Ch]
ret
Статические переменные функции
C++
int& GetStaticA()
{
static int s;
return s;
}
int& GetStaticB()
{
static int s = 42;
return s;
}
37
AVR
ldi r24, 0x4E
ldi r25, 0x01
ret
ldi r24, 0x00 ; 0
ldi r25, 0x01 ; 1
ret
ARM
movw r0, #11528 ; 0x2d08
movt r0, #1
bx lr
movw r0, #10404
movt r0, #1
bx lr
Статические переменные функции
C++
int& GetStaticA()
{
static int s;
return s;
}
int& GetStaticB()
{
static int s = 42;
return s;
}
38
PowerPC
lis r3, 0x6
addi r3,r3,0x964C
blr
lis r3,0x5
addi r3,r3,0xECC8
blr
MicroBlaze
imm 0x9009
addik r3, r0, 0x7030
rtsd r15, 8
imm 0x9008
addik r3, r0, 0x7520
rtsd r15, 8
Статические переменные функции
C++
int InitStaticC();
int& GetStaticC()
{
static int s = InitStaticC();
return s;
}
39
x86
mov eax,fs:[0000002Ch]
mov ecx,[__tls_index]
mov ecx,[eax+ecx*4]
mov eax,[0040754Ch]
cmp eax,[ecx+4]
jle @1
push 40754Ch
call __Init_thread_header
add esp,4
cmp [40754Ch],0FFFFFFFFh
jne @1
mov dword ptr [ebp-4],0
call InitStaticC
push 40754Ch
mov dword ptr [00407548h],eax
call __Init_thread_footer
add esp,4
@1:
mov eax,407548h
ret
Статические переменные функции
C++
BaseClass* GetStaticD()
{
static DerivedClass obj;
return &obj;
}
40
x86
mov eax,fs:[0000002Ch]
mov ecx,[__tls_index]
mov ecx,[eax+ecx*4]
mov eax,[0040756Ch]
cmp eax,[ecx+4]
jle @1
push 40756Ch
call __Init_thread_header
add esp,4
cmp [40756Ch],0FFFFFFFFh
jne @1
mov dword ptr [ebp-4],0
mov ecx,407550h
call ??0DerivedClass@@QAE@XZ
push @2
call _atexit
mov [407550h],eax
call __Init_thread_footer
add esp,4
@1:
mov eax,407550h
ret
@2:
mov ecx,407550h
jmp ??1BaseClass@@UAE@XZ
Статические переменные функции
C++
int InitStaticC();
int& GetStaticC()
{
static int s = InitStaticC();
return s;
}
41
x64
mov ecx,[_tls_index]
mov rax,gs:[58h]
mov edx,4
mov rcx,[rax+rcx*8]
mov eax,[rdx+rcx]
cmp [140008920h],eax
jle @1
lea rcx,[140008920h]
call _Init_thread_header
cmp [140008920h], -1
jne @1
call InitStaticC
mov [14000891Ch],eax
lea rcx,[140008920h]
call _Init_thread_footer
@1:
lea rax,[14000891Ch]
ret
Статические переменные функции
C++
BaseClass* GetStaticD()
{
static DerivedClass obj;
return &obj;
}
42
x64
mov ecx,[_tls_index]
mov rax,gs:[58h]
mov edx,4
mov rcx,[rax+rcx*8]
mov eax,[rdx+rcx]
cmp [140008960h],eax
jle @1
lea rcx,[140008960h]
call _Init_thread_header
cmp [140008960h],-1
jne @1
lea rbx,[14000891Ch]
mov rcx,rbx
call ??0DerivedClass@@QEAA@XZ
lea rcx,[@3]
call atexit
nop
lea rcx,[140008960h]
call _Init_thread_footer
mov rax,rbx
jmp @2
@1:
lea rax,[14000891Ch]
@2:
ret
@3:
lea rcx,[140008928h]
jmp ??1BaseClass@@UEAA@XZ
Статические переменные функции
C++
int InitStaticC();
int& GetStaticC()
{
static int s = InitStaticC();
return s;
}
43
ARM
push {r4, lr}
ldr r4, [pc, #56] // @d1
ldr.w r3, [r4, #200]
lsls r1, r3, #31
bpl.n @1
@2:
ldr r0, [pc, #48] ; @d2
pop {r4, pc} // return
@1:
add.w r0, r4, #200
blx 8958 <_init+0x54>
cmp r0, #0
beq.n @2
bl <test_6::InitStaticC()>
str.w r0, [r4, #204]
add.w r0, r4, #200
blx 89a4 <_init+0xa0>
// atexit
ldr r0, [pc, #16]
pop {r4, pc} // return
ldr r0, [pc, #16] // @d1
blx 8a10 <_init+0x10c>
blx 898c <_init+0x88>
nop
@d1: .word 0x00012dd4
//GetStaticC()::s
@d2: .word 0x00012dd0
// guard GetStaticC()::s
Статические переменные функции
C++
int InitStaticC();
int& GetStaticC()
{
static int s = InitStaticC();
return s;
}
44
AVR
push r28
push r29
lds r24, 0x0152 ; <guard GetStaticC()::s>
cpse r24, r1
rjmp @1
call InitStaticC
sts 0x0151, r25
sts 0x0150, r24 ; <GetStaticC()::s>
ldi r24, 0x01
sts 0x0152, r24 ; <guard GetStaticC()::s>
@1:
ldi r24, 0x50 ; 80
ldi r25, 0x01 ; 1
pop r29
pop r28
ret
00800152 00000008 b guard variable for test_6::GetStaticC()::s
Статические переменные функции
C++
int InitStaticC();
int& GetStaticC()
{
static int s = InitStaticC();
return s;
}
45
PowerPC
stwu r1,-24(r1)
mflr r0
stw r30,16(r1)
lis r30,6
stw r31,20(r1)
addi r31,r30,-27072
mr r3,r31
stw r29,12(r1)
stw r0,28(r1)
bl
<__cxa_guard_acquir
e>
cmpwi cr7,r3,0
lis r29,6
bne- cr7,@1
lwz r0,28(r1)
addi r3,r29,-27064
lwz r30,16(r1)
lwz r29,12(r1)
lwz r31,20(r1)
mtlr r0
addi r1,r1,24
blr
@1:
bl
<test_6::InitStatic
C()>
stw r3,-27064(r29)
mr r3,r31
bl
<__cxa_guard_releas
e>
lwz r0,28(r1)
addi r3,r29,-27064
lwz r30,16(r1)
lwz r29,12(r1)
lwz r31,20(r1)
mtlr r0
addi r1,r1,24
blr
mr r29,r3
addi r3,r30,-27072
bl <__cxa_guard_abort>
mr r3,r29
bl <_Unwind_Resume>
Статические переменные функции
C++
BaseClass* GetStaticE()
{
static char obj[sizeof(DerivedClass)];
static BaseClass* target;
if (!target)
{
target = new(obj)DerivedClass();
}
return target;
}
46
x86
mov eax,dword ptr ds:[0040758Ch]
test eax,eax
jne @1
mov dword ptr [ebp-10h],407570h
mov ecx,407570h
mov dword ptr [ebp-4],eax
call ??0DerivedClass@@QAE@XZ
mov dword ptr ds:[0040758Ch],eax
@1:
ret
Статические переменные функции
C++
BaseClass* GetStaticE()
{
static char obj[sizeof(DerivedClass)];
static BaseClass* target;
if (!target)
{
target = new(obj)DerivedClass();
}
return target;
}
47
x64
mov rax,qword ptr [1400089A0h]
test rax,rax
jne @1
lea rcx,[140008968h]
mov qword ptr [rsp+40h],rcx
call ??0DerivedClass@@QEAA@XZ
nop
mov qword ptr [1400089A0h],rax
@1:
ret
Статические переменные функции
C++
BaseClass* GetStaticE()
{
static char obj[sizeof(DerivedClass)];
static BaseClass* target;
if (!target)
{
target = new(obj)DerivedClass();
}
return target;
}
48
ARM
push {r3, r4, r5, lr}
ldr r4, [pc, #20] ; @d1
ldr r0, [r4, #32]
cbz r0, @1
pop {r3, r4, r5, pc}
@1:
adds r5, r4, #4
mov r0, r5
bl <DerivedClass::DerivedClass()>
mov r0, r5
str r5, [r4, #32]
pop {r3, r4, r5, pc}
@d1: .word 0x00012d08
Статические переменные функции
C++
BaseClass* GetStaticE()
{
static char obj[sizeof(DerivedClass)];
static BaseClass* target;
if (!target)
{
target = new(obj)DerivedClass();
}
return target;
}
49
AVR
lds r24, 0x017E
lds r25, 0x017F
or r24, r25
brne @1
sts 0x0173, r1
sts 0x0172, r1
sts 0x0175, r1
sts 0x0174, r1
sts 0x0177, r1
sts 0x0176, r1
ldi r24, 0x3A
ldi r25, 0x01
sts 0x0171, r25
sts 0x0170, r24
sts 0x0179, r1
sts 0x0178, r1
sts 0x017B, r1
sts 0x017A, r1
sts 0x017D, r1
sts 0x017C, r1
ldi r24, 0x70
ldi r25, 0x01
sts 0x017F, r25
sts 0x017E, r24
@1:
lds r24, 0x017E
lds r25, 0x017F
ret
Статические переменные функции
C++
BaseClass* GetStaticE()
{
static char obj[sizeof(DerivedClass)];
static BaseClass* target;
if (!target)
{
target = new(obj)DerivedClass();
}
return target;
}
50
PowerPC
stwu r1,-16(r1)
mflr r0
stw r0,20(r1)
stw r31,12(r1)
lis r31,6
stw r30,8(r1)
lwz r0,-
27056(r31)
cmpwi cr7,r0,0
beq- cr7,@1
lwz r0,20(r1)
lwz r3,-
27056(r31)
lwz r30,8(r1)
lwz r31,12(r1)
mtlr r0
addi r1,r1,16
blr
lis r4,6
li r3,28
addi r4,r4,-25724
bl <operator new(unsigned int,
void*)>
mr r30,r3
bl
<DerivedClass::DerivedClass(
)>
stw r30,-27056(r31)
lwz r0,20(r1)
lwz r30,8(r1)
@1:
lwz r3,-27056(r31)
lwz r31,12(r1)
mtlr r0
addi r1,r1,16
blr
Статические переменные функции
C++
BaseClass* GetStaticE()
{
static char obj[sizeof(DerivedClass)];
static BaseClass* target;
if (!target)
{
target = new(obj)DerivedClass();
}
return target;
}
51
MicroBlaze
imm -28663
lwi r3, r0, 28640
addik r1, r1, -28
beqid r3, @1
swi r15, r1, 0
lwi r15, r1, 0
rtsd r15, 8
addik r1, r1, 28
@1:
imm -28663
addik r5, r0, 28644
imm -1
brlid r15, <DerivedClass::DerivedClass()>
imm -28663
addik r3, r0, 28644
lwi r15, r1, 0
imm -28663
swi r3, r0, 28640
Статические переменные функции
C++
template<int X>
Point GetStaticF()
{
static Point staticFPoint;
return staticFPoint;
}
52
x86
??$GetStaticF@$00@test_6@@YA?AUPoint@@XZ:
mov eax,
[?staticFPoint@?1???$GetStaticF@$00@test_6@@YA?AUPoint@@XZ@4U2@A]
mov edx,dword ptr ds:[407594h]
ret
??$GetStaticF@$01@test_6@@YA?AUPoint@@XZ:
mov eax, [?staticFPoint@?1???$GetStaticF@$01@test_6@@YA?AUPoint@@XZ@4U2@A]
mov edx,dword ptr ds:[40759Ch]
ret
??$GetStaticF@$02@test_6@@YA?AUPoint@@XZ:
mov eax, [?staticFPoint@?1???$GetStaticF@$02@test_6@@YA?AUPoint@@XZ@4U2@A]
mov edx,dword ptr ds:[4075A4h]
ret
Статические переменные функции
C++
template<int X>
Point GetStaticF()
{
static Point staticFPoint;
return staticFPoint;
}
53
x64
??$GetStaticF@$00@test_6@@YA?AUPoint@@XZ:
movups xmm0,xmmword ptr 
[?staticFPoint@?1???$GetStaticF@$00@test_6@@YA?AUPoint@@XZ@4U2@A]
mov rax,rcx
movups xmmword ptr [rcx],xmm0
ret
??$GetStaticF@$01@test_6@@YA?AUPoint@@XZ:
movups xmm0,xmmword ptr 
[?staticFPoint@?1???$GetStaticF@$01@test_6@@YA?AUPoint@@XZ@4U2@A]
mov rax,rcx
movups xmmword ptr [rcx],xmm0
ret
??$GetStaticF@$02@test_6@@YA?AUPoint@@XZ:
movups xmm0,xmmword ptr 
[?staticFPoint@?1???$GetStaticF@$02@test_6@@YA?AUPoint@@XZ@4U2@A]
mov rax,rcx
movups xmmword ptr [rcx],xmm0
ret
Статические переменные функции
C++
template<int X>
Point GetStaticF()
{
static Point staticFPoint;
return staticFPoint;
}
54
ARM
<Point test_6::GetStaticF<1>()>:
movw r2, #11788
movt r2, #1
mov r3, r0
ldmia.w r2, {r0, r1}
stmia.w r3, {r0, r1}
mov r0, r3
bx lr
nop
<Point test_6::GetStaticF<2>()>:
movw r2, #11780
movt r2, #1
mov r3, r0
ldmia.w r2, {r0, r1}
stmia.w r3, {r0, r1}
mov r0, r3
bx lr
nop
<Point test_6::GetStaticF<3>()>:
movw r2, #11772
movt r2, #1
mov r3, r0
ldmia.w r2, {r0, r1}
stmia.w r3, {r0, r1}
mov r0, r3
bx lr
nop
Статические переменные функции
C++
template<int X>
Point GetStaticF()
{
static Point staticFPoint;
return staticFPoint;
}
55
AVR
<Point test_6::GetStaticF<1>()>:
lds r22, 0x0186
lds r23, 0x0187
lds r24, 0x0188
lds r25, 0x0189
ret
<Point test_6::GetStaticF<2>()>:
lds r22, 0x018A
lds r23, 0x018B
lds r24, 0x018C
lds r25, 0x018D
ret
<Point test_6::GetStaticF<3>()>:
lds r22, 0x018E
lds r23, 0x018F
lds r24, 0x0190
lds r25, 0x0191
ret
Статические переменные функции
C++
template<int X>
Point GetStaticF()
{
static Point staticFPoint;
return staticFPoint;
}
56
PowerPC
<Point test_6::GetStaticF<1>()>:
lis r9,6
addi r9,r9,-26872
lwz r3,0(r9)
lwz r4,4(r9)
blr
<Point test_6::GetStaticF<2>()>:
lis r9,6
addi r9,r9,-26880
lwz r3,0(r9)
lwz r4,4(r9)
blr
<Point test_6::GetStaticF<3>()>:
lis r9,6
addi r9,r9,-26888
lwz r3,0(r9)
lwz r4,4(r9)
blr
Статические переменные функции
C++
template<int X>
Point GetStaticF()
{
static Point staticFPoint;
return staticFPoint;
}
57
MicroBlaze
<Point test_6::GetStaticF<1>()>:
addk r3, r5, r0
imm -28663
lwi r4, r0, 29140
imm -28663
lwi r5, r0, 29144
swi r4, r3, 0
swi r5, r3, 4
rtsd r15, 8
<Point test_6::GetStaticF<2>()>:
addk r3, r5, r0
imm -28663
lwi r4, r0, 29132
imm -28663
lwi r5, r0, 29136
swi r4, r3, 0
swi r5, r3, 4
rtsd r15, 8
<Point test_6::GetStaticF<3>()>:
addk r3, r5, r0
imm -28663
lwi r4, r0, 29124
imm -28663
lwi r5, r0, 29128
swi r4, r3, 0
swi r5, r3, 4
rtsd r15, 8
Исключения
Реализация сильно зависит от компилятора и от операционной системы
В основе лежат нетривиальные концепции
Очень большой объём ассемблерного кода
Оставим для самостоятельного изучения
58
Итоги
1. Магии нет
2. Многое из сказанного - ложь
● примеры кода сильно упрощены
● приходилось принимать меры против оптимизаций
1. С++ - быстрый язык, потери производительности возникают в предсказуемых
местах
2. Не бойтесь, но запаситесь терпением
59
Спасибо за внимание!
А теперь - вопросы!
60
Алексей Ткаченко, ОАО “Пеленг”
tkachenko@peleng.by
alexey.tkachenko@gmail.com

More Related Content

What's hot

Лекция 8: Многопоточное программирование: Intel Threading Building Blocks
Лекция 8: Многопоточное программирование: Intel Threading Building BlocksЛекция 8: Многопоточное программирование: Intel Threading Building Blocks
Лекция 8: Многопоточное программирование: Intel Threading Building Blocks
Mikhail Kurnosov
 
Опыт разработки статического анализатора кода
Опыт разработки статического анализатора кодаОпыт разработки статического анализатора кода
Опыт разработки статического анализатора кода
Andrey Karpov
 
Address Sanitizer или как сделать программы на c/с++ надежнее и безопаснее (К...
Address Sanitizer или как сделать программы на c/с++ надежнее и безопаснее (К...Address Sanitizer или как сделать программы на c/с++ надежнее и безопаснее (К...
Address Sanitizer или как сделать программы на c/с++ надежнее и безопаснее (К...
Ontico
 

What's hot (20)

SWIG — cоздание мультиязыковых интерфейсов для C/C++ библиотек
SWIG — cоздание мультиязыковых интерфейсов для C/C++ библиотекSWIG — cоздание мультиязыковых интерфейсов для C/C++ библиотек
SWIG — cоздание мультиязыковых интерфейсов для C/C++ библиотек
 
Python&Printer / Андрей Пучко / penta.by
Python&Printer / Андрей Пучко / penta.byPython&Printer / Андрей Пучко / penta.by
Python&Printer / Андрей Пучко / penta.by
 
Когда в C# не хватает C++ . Часть 3.
Когда в C# не хватает C++. Часть 3. Когда в C# не хватает C++. Часть 3.
Когда в C# не хватает C++ . Часть 3.
 
Когда в C# не хватает C++ . Часть 2.
Когда в C# не хватает C++. Часть 2.Когда в C# не хватает C++. Часть 2.
Когда в C# не хватает C++ . Часть 2.
 
Когда в C# не хватает C++
Когда в C# не хватает C++Когда в C# не хватает C++
Когда в C# не хватает C++
 
Лекция 8: Многопоточное программирование: Intel Threading Building Blocks
Лекция 8: Многопоточное программирование: Intel Threading Building BlocksЛекция 8: Многопоточное программирование: Intel Threading Building Blocks
Лекция 8: Многопоточное программирование: Intel Threading Building Blocks
 
Дмитрий Прокопцев — R-ссылки в С++11
Дмитрий Прокопцев — R-ссылки в С++11Дмитрий Прокопцев — R-ссылки в С++11
Дмитрий Прокопцев — R-ссылки в С++11
 
Miasm defcon russia 23
Miasm defcon russia 23Miasm defcon russia 23
Miasm defcon russia 23
 
Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!
Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!
Алексей Куканов — Параллелизм в C++: управляйте приложением, а не потоками!
 
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...
 
Евгений Зуев, С++ в России: Стандарт языка и его реализация
Евгений Зуев, С++ в России: Стандарт языка и его реализацияЕвгений Зуев, С++ в России: Стандарт языка и его реализация
Евгений Зуев, С++ в России: Стандарт языка и его реализация
 
C:\fakepath\кмсзи экз
C:\fakepath\кмсзи   экзC:\fakepath\кмсзи   экз
C:\fakepath\кмсзи экз
 
Опыт разработки статического анализатора кода
Опыт разработки статического анализатора кодаОпыт разработки статического анализатора кода
Опыт разработки статического анализатора кода
 
ПВТ - весна 2015 - Лекция 4. Шаблоны многопоточного программирования
ПВТ - весна 2015 - Лекция 4. Шаблоны многопоточного программированияПВТ - весна 2015 - Лекция 4. Шаблоны многопоточного программирования
ПВТ - весна 2015 - Лекция 4. Шаблоны многопоточного программирования
 
SECON'2016. Кочков Антон, Рютин Борис, Radare2 - от A до Z
SECON'2016. Кочков Антон, Рютин Борис, Radare2 - от A до ZSECON'2016. Кочков Антон, Рютин Борис, Radare2 - от A до Z
SECON'2016. Кочков Антон, Рютин Борис, Radare2 - от A до Z
 
Address Sanitizer или как сделать программы на c/с++ надежнее и безопаснее (К...
Address Sanitizer или как сделать программы на c/с++ надежнее и безопаснее (К...Address Sanitizer или как сделать программы на c/с++ надежнее и безопаснее (К...
Address Sanitizer или как сделать программы на c/с++ надежнее и безопаснее (К...
 
Павел Довгалюк, Обратная отладка
Павел Довгалюк, Обратная отладкаПавел Довгалюк, Обратная отладка
Павел Довгалюк, Обратная отладка
 
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и Javascript
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и JavascriptСергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и Javascript
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и Javascript
 
Лекция 3. Виртуальные топологии в MPI. Параллельные алгоритмы в стандарте MPI...
Лекция 3. Виртуальные топологии в MPI. Параллельные алгоритмы в стандарте MPI...Лекция 3. Виртуальные топологии в MPI. Параллельные алгоритмы в стандарте MPI...
Лекция 3. Виртуальные топологии в MPI. Параллельные алгоритмы в стандарте MPI...
 
Евгений Крутько — Опыт внедрения технологий параллельных вычислений для повыш...
Евгений Крутько — Опыт внедрения технологий параллельных вычислений для повыш...Евгений Крутько — Опыт внедрения технологий параллельных вычислений для повыш...
Евгений Крутько — Опыт внедрения технологий параллельных вычислений для повыш...
 

Similar to C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - Алексей Ткаченко

20130429 dynamic c_c++_program_analysis-alexey_samsonov
20130429 dynamic c_c++_program_analysis-alexey_samsonov20130429 dynamic c_c++_program_analysis-alexey_samsonov
20130429 dynamic c_c++_program_analysis-alexey_samsonov
Computer Science Club
 
SAMag2007 Conference: PostgreSQL 8.3 presentation
SAMag2007 Conference: PostgreSQL 8.3 presentationSAMag2007 Conference: PostgreSQL 8.3 presentation
SAMag2007 Conference: PostgreSQL 8.3 presentation
Nikolay Samokhvalov
 
Развитие технологий генерации эксплойтов на основе анализа бинарного кода
Развитие технологий генерации эксплойтов на основе анализа бинарного кодаРазвитие технологий генерации эксплойтов на основе анализа бинарного кода
Развитие технологий генерации эксплойтов на основе анализа бинарного кода
Positive Hack Days
 
ADD 2011: Статический анализ Си++ кода
ADD 2011: Статический анализ Си++ кодаADD 2011: Статический анализ Си++ кода
ADD 2011: Статический анализ Си++ кода
Andrey Karpov
 

Similar to C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - Алексей Ткаченко (20)

Как приручить дракона: введение в LLVM
Как приручить дракона: введение в LLVMКак приручить дракона: введение в LLVM
Как приручить дракона: введение в LLVM
 
C++ exceptions
C++ exceptionsC++ exceptions
C++ exceptions
 
20130429 dynamic c_c++_program_analysis-alexey_samsonov
20130429 dynamic c_c++_program_analysis-alexey_samsonov20130429 dynamic c_c++_program_analysis-alexey_samsonov
20130429 dynamic c_c++_program_analysis-alexey_samsonov
 
Использование C++ для низкоуровневой платформозависимой разработки — Кирилл ...
 Использование C++ для низкоуровневой платформозависимой разработки — Кирилл ... Использование C++ для низкоуровневой платформозависимой разработки — Кирилл ...
Использование C++ для низкоуровневой платформозависимой разработки — Кирилл ...
 
DSLs in Lisp and Clojure
DSLs in Lisp and ClojureDSLs in Lisp and Clojure
DSLs in Lisp and Clojure
 
200 open source проектов спустя: опыт статического анализа исходного кода
200 open source проектов спустя:опыт статического анализа исходного кода200 open source проектов спустя:опыт статического анализа исходного кода
200 open source проектов спустя: опыт статического анализа исходного кода
 
200 open source проектов спустя: опыт статического анализа исходного кода
200 open source проектов спустя: опыт статического анализа исходного кода200 open source проектов спустя: опыт статического анализа исходного кода
200 open source проектов спустя: опыт статического анализа исходного кода
 
На что нужно обратить внимание при обзоре кода разрабатываемой библиотеки
На что нужно обратить внимание при обзоре кода разрабатываемой библиотекиНа что нужно обратить внимание при обзоре кода разрабатываемой библиотеки
На что нужно обратить внимание при обзоре кода разрабатываемой библиотеки
 
Как не сделать врагами архитектуру и оптимизацию, Кирилл Березин, Mail.ru Group
Как не сделать врагами архитектуру и оптимизацию, Кирилл Березин, Mail.ru GroupКак не сделать врагами архитектуру и оптимизацию, Кирилл Березин, Mail.ru Group
Как не сделать врагами архитектуру и оптимизацию, Кирилл Березин, Mail.ru Group
 
SAMag2007 Conference: PostgreSQL 8.3 presentation
SAMag2007 Conference: PostgreSQL 8.3 presentationSAMag2007 Conference: PostgreSQL 8.3 presentation
SAMag2007 Conference: PostgreSQL 8.3 presentation
 
11 встреча — Введение в GPGPU (А. Свириденков)
11 встреча — Введение в GPGPU (А. Свириденков)11 встреча — Введение в GPGPU (А. Свириденков)
11 встреча — Введение в GPGPU (А. Свириденков)
 
введение в Gpu
введение в Gpuвведение в Gpu
введение в Gpu
 
Развитие технологий генерации эксплойтов на основе анализа бинарного кода
Развитие технологий генерации эксплойтов на основе анализа бинарного кодаРазвитие технологий генерации эксплойтов на основе анализа бинарного кода
Развитие технологий генерации эксплойтов на основе анализа бинарного кода
 
OpenACC short review
OpenACC short reviewOpenACC short review
OpenACC short review
 
Статический анализ Си++ кода
Статический анализ Си++ кодаСтатический анализ Си++ кода
Статический анализ Си++ кода
 
ADD 2011: Статический анализ Си++ кода
ADD 2011: Статический анализ Си++ кодаADD 2011: Статический анализ Си++ кода
ADD 2011: Статический анализ Си++ кода
 
Статический анализ кода: Что? Как? Зачем?
Статический анализ кода: Что? Как? Зачем?Статический анализ кода: Что? Как? Зачем?
Статический анализ кода: Что? Как? Зачем?
 
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++ Юрий Ефимочев, Компилируемые в реальном времени DSL для С++
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++
 
C++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
C++ CoreHard Autumn 2018. Полезный constexpr - Антон ПолухинC++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
C++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
 
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
 

More from corehard_by

C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
corehard_by
 
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia KazakovaC++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
corehard_by
 
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
corehard_by
 

More from corehard_by (20)

C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...
C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...
C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...
 
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...
 
C++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений Охотников
C++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений ОхотниковC++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений Охотников
C++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений Охотников
 
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титов
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр ТитовC++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титов
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титов
 
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...
 
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья ШишковC++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
 
C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...
C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...
C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...
 
C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...
C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...
C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...
 
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...
 
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
 
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
 
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филонов
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел ФилоновC++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филонов
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филонов
 
C++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan Čukić
C++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan ČukićC++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan Čukić
C++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan Čukić
 
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia KazakovaC++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
 
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
 
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019
 
Как помочь и как помешать компилятору. Андрей Олейников ➠ CoreHard Autumn 2019
Как помочь и как помешать компилятору. Андрей Олейников ➠  CoreHard Autumn 2019Как помочь и как помешать компилятору. Андрей Олейников ➠  CoreHard Autumn 2019
Как помочь и как помешать компилятору. Андрей Олейников ➠ CoreHard Autumn 2019
 
Автоматизируй это. Кирилл Тихонов ➠ CoreHard Autumn 2019
Автоматизируй это. Кирилл Тихонов ➠  CoreHard Autumn 2019Автоматизируй это. Кирилл Тихонов ➠  CoreHard Autumn 2019
Автоматизируй это. Кирилл Тихонов ➠ CoreHard Autumn 2019
 
Статичный SQL в С++14. Евгений Захаров ➠ CoreHard Autumn 2019
Статичный SQL в С++14. Евгений Захаров ➠  CoreHard Autumn 2019Статичный SQL в С++14. Евгений Захаров ➠  CoreHard Autumn 2019
Статичный SQL в С++14. Евгений Захаров ➠ CoreHard Autumn 2019
 
Как не подавиться большим старым проектом. Юрий Минаев ➠ CoreHard Autumn 2019
Как не подавиться большим старым проектом. Юрий Минаев ➠  CoreHard Autumn 2019Как не подавиться большим старым проектом. Юрий Минаев ➠  CoreHard Autumn 2019
Как не подавиться большим старым проектом. Юрий Минаев ➠ CoreHard Autumn 2019
 

C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - Алексей Ткаченко

  • 1. Кодогенерация C++ кроссплатформенно часть 2 Алексей Ткаченко, ОАО “Пеленг” tkachenko@peleng.by alexey.tkachenko@gmail.com
  • 2. О чём доклад? ● сопоставление языковых конструкций C++ с генерируемым машинным кодом ● сравнение генерации для различных платформ и архитектур ● особенности архитектур в контексте кроссплатформенности ● развенчание мифов 2
  • 3. Исходный код Исходный код Фазы компиляции 3 Лексический анализ Синтаксический анализ Семантический анализ Оптимизация Кодогенерация Исходный код Исходный код Исполняемая программа
  • 4. Платформы Рассмотрим ● Intel x86 (CISC, 32bit) / MSVS 2015 (Windows 10) ● x86-64 (CISC, 64bit) / MSVS 2015 (Windows 10) ● ARM Cortex-A7 (RISC, 32bit) / GCC 4.6.3 (Debian 7 @ CubieBoard2) ● Atmel AVR (AVR RISC, 8bit) / GCC 4.8.1, Arduino (Windows 10) ● IBM PowerPC (RISC, 32bit) / Xilinx EDK 14.7 (Ubuntu 17) ● Xilinx Microblaze (RISC, 32bit, over FPGA) / Xilinx EDK 14.7 (Ubuntu 17) 4
  • 5. Вызов метода C++ class BaseClass { ptrdiff_t Method1(ptrdiff_t a); ptrdiff_t Method2(ptrdiff_t a) const; BaseClass operator~(); virtual ptrdiff_t Method3(ptrdiff_t a); } BaseClass* obj = new BaseClass(); ptrdiff_t result = obj->Method1(1) + 1; x86 push 1 mov ecx,esi ; this call ?Method1@BaseClass@@QAEHH@Z mov edi,eax x64 mov edx,1 mov rcx,rbx call ?Method1@BaseClass@@QEAA_J_J@Z mov rdi,rax 5
  • 6. Вызов метода C++ class BaseClass { ptrdiff_t Method1(ptrdiff_t a); ptrdiff_t Method2(ptrdiff_t a) const; BaseClass operator~(); virtual ptrdiff_t Method3(ptrdiff_t a); } BaseClass* obj = new BaseClass(); ptrdiff_t result = obj->Method1(1) + 1; 6 AVR ldi r22, 0x01 ; 1 ldi r23, 0x00 ; 0 movw r24, r28 call <BaseClass::Method1(int)> movw r16, r24 ARM mov r0, r4 movs r1, #1 bl <BaseClass::Method1(int)> adds r5, r0, #1
  • 7. Вызов метода C++ class BaseClass { ptrdiff_t Method1(ptrdiff_t a); ptrdiff_t Method2(ptrdiff_t a) const; BaseClass operator~(); virtual ptrdiff_t Method3(ptrdiff_t a); } BaseClass* obj = new BaseClass(); ptrdiff_t result = obj->Method1(1) + 1; 7 PowerPC mr r3,r31 li r4,1 bl BaseClass::Method1(int) addi r3,r29,1 MicroBlaze addk r19, r3, r0 addk r5, r19, r0 brlid r15, BaseClass::Method1(int) addik r6, r0, 1
  • 8. Вызов константного метода C++ class BaseClass { ptrdiff_t Method1(ptrdiff_t a); ptrdiff_t Method2(ptrdiff_t a) const; BaseClass operator~(); virtual ptrdiff_t Method3(ptrdiff_t a); } BaseClass* obj = new BaseClass(); ptrdiff_t result = obj->Method2(2) + 2; x86 push 2 mov ecx,esi call ?Method2@BaseClass@@QBEHH@Z add eax, 2 x64 mov edx,2 mov rcx,rbx call ?Method2@BaseClass@@QEBA_J_J@Z add rax, 2 8
  • 9. Вызов константного метода C++ class BaseClass { ptrdiff_t Method1(ptrdiff_t a); ptrdiff_t Method2(ptrdiff_t a) const; BaseClass operator~(); virtual ptrdiff_t Method3(ptrdiff_t a); } BaseClass* obj = new BaseClass(); ptrdiff_t result = obj->Method2(2) + 2; 9 AVR movw r24, r28 call <BaseClass::Method2(int) const> movw r16, r24 subi r16, 0xFE sbci r17, 0xFF ARM mov r0, r4 movs r1, #2 bl <BaseClass::Method2(int) const> adds r5, r0, #2
  • 10. Вызов константного метода C++ class BaseClass { ptrdiff_t Method1(ptrdiff_t a); ptrdiff_t Method2(ptrdiff_t a) const; BaseClass operator~(); virtual ptrdiff_t Method3(ptrdiff_t a); } BaseClass* obj = new BaseClass(); ptrdiff_t result = obj->Method2(2) + 2; 10 PowerPC mr r3,r31 li r4,2 bl <BaseClass::Method2(int) const> addi r3,r29,2 MicroBlaze addk r19, r3, r0 addk r5, r19, r0 brlid r15, <BaseClass::Method2(int) const> addik r22, r3, 2
  • 11. Вызов оператора C++ class BaseClass { ptrdiff_t Method1(ptrdiff_t a); ptrdiff_t Method2(ptrdiff_t a) const; BaseClass operator~(); virtual ptrdiff_t Method3(ptrdiff_t a); } BaseClass* obj = new BaseClass(); BaseClass op = ~*obj; x86 mov ecx,esi call ??SBaseClass@@QAE?AV0@XZ x64 mov rcx,rbx call ??SBaseClass@@QEAA?AV0@XZ 11
  • 12. Вызов оператора C++ class BaseClass { ptrdiff_t Method1(ptrdiff_t a); ptrdiff_t Method2(ptrdiff_t a) const; BaseClass operator~(); virtual ptrdiff_t Method3(ptrdiff_t a); } BaseClass* obj = new BaseClass(); BaseClass op = ~*obj; 12 AVR movw r22, r16 movw r24, r28 adiw r24, 0x01 call <BaseClass::operator~()> ARM mov r1, r4 bl <BaseClass::operator~()>
  • 13. Вызов оператора C++ class BaseClass { ptrdiff_t Method1(ptrdiff_t a); ptrdiff_t Method2(ptrdiff_t a) const; BaseClass operator~(); virtual ptrdiff_t Method3(ptrdiff_t a); } BaseClass* obj = new BaseClass(); ptrdiff_t result = ~*obj; 13 PowerPC mr r3,r31 bl <BaseClass::operator~()> MicroBlaze addk r19, r3, r0 addk r6, r19, r0 brlid r15, <BaseClass::operator~()>
  • 14. Вызов конструктора C++ class BaseClass { protected: ptrdiff_t x; ptrdiff_t y; ptrdiff_t z; public: BaseClass(); virtual ~BaseClass(); }; BaseClass::BaseClass() : x(), y(), z() {} x86 mov dword ptr [ecx],offset ??_7BaseClass@@6B@ mov eax,ecx mov dword ptr [ecx+4],0 mov dword ptr [ecx+8],0 mov dword ptr [ecx+0Ch],0 ret x64 lea rax,[??_7BaseClass@@6B@] mov qword ptr [rcx],rax xor eax,eax mov qword ptr [rcx+8],rax mov qword ptr [rcx+10h],rax mov qword ptr [rcx+18h],rax mov rax,rcx ret 14
  • 15. Вызов конструктора C++ class BaseClass { protected: ptrdiff_t x; ptrdiff_t y; ptrdiff_t z; public: BaseClass(); virtual ~BaseClass(); }; BaseClass::BaseClass() : x(), y(), z() {} 15 ARM ldr r2, [pc, #12] ; @VPTR movs r3, #0 str r3, [r0, #4] str r3, [r0, #8] str r2, [r0, #0] str r3, [r0, #12] bx lr nop @VPTR: .word 0x00009f60
  • 16. Вызов конструктора C++ class BaseClass { protected: ptrdiff_t x; ptrdiff_t y; ptrdiff_t z; public: BaseClass(); virtual ~BaseClass(); }; BaseClass::BaseClass() : x(), y(), z() {} 16 PowerPC lis r9,5 li r0,0 addi r9,r9,0xCDE8 stw r0,12(r3) stw r9,0(r3) stw r0,4(r3) stw r0,8(r3) blr MicroBlaze imm 0x9008 addik r3, r0, 0x45E4 swi r0, r5, 4 swi r0, r5, 8 swi r3, r5, 0 rtsd r15, 8 swi r0, r5, 12
  • 18. Вызов виртуального метода C++ class BaseClass { ptrdiff_t Method1(ptrdiff_t a); ptrdiff_t Method2(ptrdiff_t a) const; BaseClass operator~(); virtual ptrdiff_t Method3(ptrdiff_t a); } BaseClass* obj = new BaseClass(); ptrdiff_t result = obj->Method3(3) + 3; x86 mov edi,eax mov eax,dword ptr [edi] mov ecx,edi push 3 call dword ptr [eax+4] x64 mov rdi,rax mov rax,qword ptr [rdi] mov edx,3 mov rcx,rdi call qword ptr [rax+8] 18
  • 19. Вызов виртуального метода C++ class BaseClass { ptrdiff_t Method1(ptrdiff_t a); ptrdiff_t Method2(ptrdiff_t a) const; BaseClass operator~(); virtual ptrdiff_t Method3(ptrdiff_t a); } BaseClass* obj = new BaseClass(); ptrdiff_t result = obj->Method3(3) + 3; 19 AVR ld r30, Y ldd r31, Y+1 ldd r0, Z+4 ldd r31, Z+5 mov r30, r0 ARM ldr r3, [r4, #0] movs r1, #3 mov r0, r4 ldr r3, [r3, #8] blx r3 ldi r22, 0x03 ldi r23, 0x00 movw r24, r28 icall
  • 20. Вызов виртуального метода C++ class BaseClass { ptrdiff_t Method1(ptrdiff_t a); ptrdiff_t Method2(ptrdiff_t a) const; BaseClass operator~(); virtual ptrdiff_t Method3(ptrdiff_t a); } BaseClass* obj = new BaseClass(); ptrdiff_t result = obj->Method3(3) + 3; 20 PowerPC lwz r9,0(r31) li r4,3 mr r3,r31 lwz r9,8(r9) mtctr r9 bctrl MicroBlaze addk r19, r3, r0 lwi r3, r19, 0 addk r5, r19, r0 lwi r3, r3, 8 brald r15, r3
  • 21. Вызов перекрытого виртуального метода C++ class BaseClass { virtual ptrdiff_t Method3(ptrdiff_t a); } class DerivedClass : public BaseClass { public: virtual ptrdiff_t Method3(ptrdiff_t a); } BaseClass* obj = new DerivedClass(); ptrdiff_t result = obj->Method3(4) + 4; x86 mov edi,eax mov eax,dword ptr [edi] mov ecx,edi push 4 call dword ptr [eax+4] 21 x86 (virtual in base class) mov edi,eax mov eax,dword ptr [edi] mov ecx,edi push 3 call dword ptr [eax+4]
  • 22. Указатель на поле C++ class BaseClass { ptrdiff_t x; ptrdiff_t y; ptrdiff_t z; public: typedef ptrdiff_t BaseClass::* FieldPtr; FieldPtr GetField(ptrdiff_t ptr); }; BaseClass* obj = new BaseClass(1, 2, 3); BaseClass::FieldPtr field = obj- >GetField(1); ptrdiff_t value = obj->*field; x86 push 3 push 2 push 1 mov ecx,eax call ??0BaseClass@@QAE@HHH@Z mov esi,eax jmp 00403090 xor esi,esi push 1 mov ecx,esi call ?GetField@BaseClass@@QAEPQ1@HH@Z mov edi,dword ptr [eax+esi] 22
  • 23. Указатель на поле C++ class BaseClass { ptrdiff_t x; ptrdiff_t y; ptrdiff_t z; public: typedef ptrdiff_t BaseClass::* FieldPtr; FieldPtr GetField(ptrdiff_t ptr); }; BaseClass* obj = new BaseClass(1, 2, 3); BaseClass::FieldPtr field = obj- >GetField(1); ptrdiff_t value = obj->*field; x64 mov edx,1 lea r9d,[rdx+2] lea r8d,[rdx+1] mov rcx,rax call ??0BaseClass@@QEAA@_J00@Z mov rbx,rax mov edx,1 mov rcx,rbx call ?GetField@BaseClass@@QEAAPEQ1@_J_J@Z movsxd rcx,eax mov rdi,qword ptr [rcx+rbx] 23
  • 24. Указатель на поле C++ class BaseClass { ptrdiff_t x; ptrdiff_t y; ptrdiff_t z; public: typedef ptrdiff_t BaseClass::* FieldPtr; FieldPtr GetField(ptrdiff_t ptr); }; BaseClass* obj = new BaseClass(1, 2, 3); BaseClass::FieldPtr field = obj- >GetField(1); ptrdiff_t value = obj->*field; 24 ARM movs r1, #1 movs r2, #2 movs r3, #3 mov r4, r0 bl <BaseClass::BaseClass(int, int, int)> mov r0, r4 movs r1, #1 bl <BaseClass::GetField(int)> ldr r5, [r4, r0]
  • 25. Указатель на поле C++ class BaseClass { ptrdiff_t x; ptrdiff_t y; ptrdiff_t z; public: typedef ptrdiff_t BaseClass::* FieldPtr; FieldPtr GetField(ptrdiff_t ptr); }; BaseClass* obj = new BaseClass(1, 2, 3); BaseClass::FieldPtr field = obj- >GetField(1); ptrdiff_t value = obj->*field; 25 PowerPC li r4,1 li r5,2 li r6,3 bl <BaseClass::BaseClass(int, int, int)> mr r3,r31 li r4,1 bl <BaseClass::GetField(int)> lwzx r29,r31,r3
  • 26. Указатель на поле C++ class BaseClass { ptrdiff_t x; ptrdiff_t y; ptrdiff_t z; public: typedef ptrdiff_t BaseClass::* FieldPtr; FieldPtr GetField(ptrdiff_t ptr); }; BaseClass* obj = new BaseClass(1, 2, 3); BaseClass::FieldPtr field = obj- >GetField(1); ptrdiff_t value = obj->*field; 26 MicroBlaze addk r5, r3, r0 addik r6, r0, 1 addik r7, r0, 2 addik r8, r0, 3 imm ... brlid r15, BaseClass::BaseClass(int, int, int)> addk r19, r3, r0 addk r5, r19, r0 imm ... brlid r15, <BaseClass::GetField(int)> lw r22, r3, r19
  • 27. Указатель на метод C++ class BaseClass { public: typedef ptrdiff_t (BaseClass::*MethodPtr) (ptrdiff_t); MethodPtr GetMethod(ptrdiff_t); }; BaseClass* obj = new DerivedClass(); BaseClass::MethodPtr method = obj- >GetMethod(0); ptrdiff_t value = (obj->*method)(42) + 1; x86 push 0 mov ecx,esi call ?GetMethod@BaseClass@@QAEP81@AEHH@ZH@Z push 2Ah mov ecx,esi call eax 27
  • 28. Указатель на виртуальный метод C++ class BaseClass { public: typedef ptrdiff_t (BaseClass::*MethodPtr) (ptrdiff_t); MethodPtr GetMethod(ptrdiff_t); }; BaseClass* obj = new DerivedClass(); BaseClass::MethodPtr method = obj- >GetMethod(0); ptrdiff_t value = (obj->*method)(42) + 1; x86 push 1 mov ecx,esi call ?GetMethod@BaseClass@@QAEP81@AEHH@ZH@Z push 2Ah mov ecx,esi call eax mov eax,dword ptr [ecx] jmp dword ptr [eax+4] 28
  • 29. Указатель на метод C++ class BaseClass { public: typedef ptrdiff_t (BaseClass::*MethodPtr) (ptrdiff_t); MethodPtr GetMethod(ptrdiff_t); }; BaseClass* obj = new DerivedClass(); BaseClass::MethodPtr method = obj- >GetMethod(0); ptrdiff_t value = (obj->*method)(42) + 1; x64 mov edx,1 mov rcx,rbx call ?GetMethod@BaseClass@@QEAAP81@EAA_J_J@Z0@Z mov edx,2Ah mov rcx,rbx call rax 29
  • 30. Указатель на виртуальный метод C++ class BaseClass { public: typedef ptrdiff_t (BaseClass::*MethodPtr) (ptrdiff_t); MethodPtr GetMethod(ptrdiff_t); }; BaseClass* obj = new DerivedClass(); BaseClass::MethodPtr method = obj- >GetMethod(0); ptrdiff_t value = (obj->*method)(42) + 1; x64 xor edx,edx mov rcx,rbx call ?GetMethod@BaseClass@@QEAAP81@EAA_J_J@Z0@Z mov edx,2Ah mov rcx,rbx call rax mov rax,qword ptr [rcx] jmp qword ptr [rax+8] 30
  • 32. Указатель на метод C++ class BaseClass { public: typedef ptrdiff_t (BaseClass::*MethodPtr) (ptrdiff_t); MethodPtr GetMethod(ptrdiff_t ptr); }; BaseClass* obj = new DerivedClass(); BaseClass::MethodPtr method = obj- >GetMethod(0); ptrdiff_t value = (obj->*method)(42) + 1; 32 ARM movs r2, #1 add r0, sp, #16 mov r1, r4 bl BaseClass::GetMethod(int) ldr r0, [sp, #20] ldr r3, [sp, #16] lsls r2, r0, #31 it pl addpl.w r0, r4, r0, asr #1 bpl.n @1 asrs r2, r0, #1 adds r0, r4, r2 ldr r2, [r4, r2] ldr r3, [r2, r3] @1: movs r1, #42 blx r3
  • 33. Указатель на метод C++ class BaseClass { public: typedef ptrdiff_t (BaseClass::*MethodPtr) (ptrdiff_t); MethodPtr GetMethod(ptrdiff_t ptr); }; BaseClass* obj = new DerivedClass(); BaseClass::MethodPtr method = obj- >GetMethod(0); ptrdiff_t value = (obj->*method)(42) + 1; 33 PowerPC mr r3,r31 li r4,1 bl BaseClass::GetMethod(int) mr r0,r3 add r11,r31,r4 andi. r9,r0,1 beq- @1 lwzx r9,r31,r4 add r9,r9,r0 lwz r0,-1(r9) @1: mr r3,r11 li r4,42 mtctr r0 bctrl
  • 34. Указатель на метод 34 Callee Virtual callee vtable ~ VirtualA VirtualB Pointer xxxx xxx1 Pointer yyyy yyy0
  • 35. Тривиальные глобальные данные C++ int Trivial; Point EmptyPoint; int Initialized = 42; Ничего не стоят в процессе выполнения. Неинициализированные глобальные данные заполняются нулевыми байтами и не требуют хранения в загрузочном образе. Инициализированные данные хранятся в виде начальных значений в загрузочном образе. 35
  • 36. Статические переменные функции C++ int& GetStaticA() { static int s; return s; } int& GetStaticB() { static int s = 42; return s; } 36 x86 mov eax,407544h ret mov eax,407040h ret x64 lea rax,[140008918h] ret lea rax,[14000807Ch] ret
  • 37. Статические переменные функции C++ int& GetStaticA() { static int s; return s; } int& GetStaticB() { static int s = 42; return s; } 37 AVR ldi r24, 0x4E ldi r25, 0x01 ret ldi r24, 0x00 ; 0 ldi r25, 0x01 ; 1 ret ARM movw r0, #11528 ; 0x2d08 movt r0, #1 bx lr movw r0, #10404 movt r0, #1 bx lr
  • 38. Статические переменные функции C++ int& GetStaticA() { static int s; return s; } int& GetStaticB() { static int s = 42; return s; } 38 PowerPC lis r3, 0x6 addi r3,r3,0x964C blr lis r3,0x5 addi r3,r3,0xECC8 blr MicroBlaze imm 0x9009 addik r3, r0, 0x7030 rtsd r15, 8 imm 0x9008 addik r3, r0, 0x7520 rtsd r15, 8
  • 39. Статические переменные функции C++ int InitStaticC(); int& GetStaticC() { static int s = InitStaticC(); return s; } 39 x86 mov eax,fs:[0000002Ch] mov ecx,[__tls_index] mov ecx,[eax+ecx*4] mov eax,[0040754Ch] cmp eax,[ecx+4] jle @1 push 40754Ch call __Init_thread_header add esp,4 cmp [40754Ch],0FFFFFFFFh jne @1 mov dword ptr [ebp-4],0 call InitStaticC push 40754Ch mov dword ptr [00407548h],eax call __Init_thread_footer add esp,4 @1: mov eax,407548h ret
  • 40. Статические переменные функции C++ BaseClass* GetStaticD() { static DerivedClass obj; return &obj; } 40 x86 mov eax,fs:[0000002Ch] mov ecx,[__tls_index] mov ecx,[eax+ecx*4] mov eax,[0040756Ch] cmp eax,[ecx+4] jle @1 push 40756Ch call __Init_thread_header add esp,4 cmp [40756Ch],0FFFFFFFFh jne @1 mov dword ptr [ebp-4],0 mov ecx,407550h call ??0DerivedClass@@QAE@XZ push @2 call _atexit mov [407550h],eax call __Init_thread_footer add esp,4 @1: mov eax,407550h ret @2: mov ecx,407550h jmp ??1BaseClass@@UAE@XZ
  • 41. Статические переменные функции C++ int InitStaticC(); int& GetStaticC() { static int s = InitStaticC(); return s; } 41 x64 mov ecx,[_tls_index] mov rax,gs:[58h] mov edx,4 mov rcx,[rax+rcx*8] mov eax,[rdx+rcx] cmp [140008920h],eax jle @1 lea rcx,[140008920h] call _Init_thread_header cmp [140008920h], -1 jne @1 call InitStaticC mov [14000891Ch],eax lea rcx,[140008920h] call _Init_thread_footer @1: lea rax,[14000891Ch] ret
  • 42. Статические переменные функции C++ BaseClass* GetStaticD() { static DerivedClass obj; return &obj; } 42 x64 mov ecx,[_tls_index] mov rax,gs:[58h] mov edx,4 mov rcx,[rax+rcx*8] mov eax,[rdx+rcx] cmp [140008960h],eax jle @1 lea rcx,[140008960h] call _Init_thread_header cmp [140008960h],-1 jne @1 lea rbx,[14000891Ch] mov rcx,rbx call ??0DerivedClass@@QEAA@XZ lea rcx,[@3] call atexit nop lea rcx,[140008960h] call _Init_thread_footer mov rax,rbx jmp @2 @1: lea rax,[14000891Ch] @2: ret @3: lea rcx,[140008928h] jmp ??1BaseClass@@UEAA@XZ
  • 43. Статические переменные функции C++ int InitStaticC(); int& GetStaticC() { static int s = InitStaticC(); return s; } 43 ARM push {r4, lr} ldr r4, [pc, #56] // @d1 ldr.w r3, [r4, #200] lsls r1, r3, #31 bpl.n @1 @2: ldr r0, [pc, #48] ; @d2 pop {r4, pc} // return @1: add.w r0, r4, #200 blx 8958 <_init+0x54> cmp r0, #0 beq.n @2 bl <test_6::InitStaticC()> str.w r0, [r4, #204] add.w r0, r4, #200 blx 89a4 <_init+0xa0> // atexit ldr r0, [pc, #16] pop {r4, pc} // return ldr r0, [pc, #16] // @d1 blx 8a10 <_init+0x10c> blx 898c <_init+0x88> nop @d1: .word 0x00012dd4 //GetStaticC()::s @d2: .word 0x00012dd0 // guard GetStaticC()::s
  • 44. Статические переменные функции C++ int InitStaticC(); int& GetStaticC() { static int s = InitStaticC(); return s; } 44 AVR push r28 push r29 lds r24, 0x0152 ; <guard GetStaticC()::s> cpse r24, r1 rjmp @1 call InitStaticC sts 0x0151, r25 sts 0x0150, r24 ; <GetStaticC()::s> ldi r24, 0x01 sts 0x0152, r24 ; <guard GetStaticC()::s> @1: ldi r24, 0x50 ; 80 ldi r25, 0x01 ; 1 pop r29 pop r28 ret 00800152 00000008 b guard variable for test_6::GetStaticC()::s
  • 45. Статические переменные функции C++ int InitStaticC(); int& GetStaticC() { static int s = InitStaticC(); return s; } 45 PowerPC stwu r1,-24(r1) mflr r0 stw r30,16(r1) lis r30,6 stw r31,20(r1) addi r31,r30,-27072 mr r3,r31 stw r29,12(r1) stw r0,28(r1) bl <__cxa_guard_acquir e> cmpwi cr7,r3,0 lis r29,6 bne- cr7,@1 lwz r0,28(r1) addi r3,r29,-27064 lwz r30,16(r1) lwz r29,12(r1) lwz r31,20(r1) mtlr r0 addi r1,r1,24 blr @1: bl <test_6::InitStatic C()> stw r3,-27064(r29) mr r3,r31 bl <__cxa_guard_releas e> lwz r0,28(r1) addi r3,r29,-27064 lwz r30,16(r1) lwz r29,12(r1) lwz r31,20(r1) mtlr r0 addi r1,r1,24 blr mr r29,r3 addi r3,r30,-27072 bl <__cxa_guard_abort> mr r3,r29 bl <_Unwind_Resume>
  • 46. Статические переменные функции C++ BaseClass* GetStaticE() { static char obj[sizeof(DerivedClass)]; static BaseClass* target; if (!target) { target = new(obj)DerivedClass(); } return target; } 46 x86 mov eax,dword ptr ds:[0040758Ch] test eax,eax jne @1 mov dword ptr [ebp-10h],407570h mov ecx,407570h mov dword ptr [ebp-4],eax call ??0DerivedClass@@QAE@XZ mov dword ptr ds:[0040758Ch],eax @1: ret
  • 47. Статические переменные функции C++ BaseClass* GetStaticE() { static char obj[sizeof(DerivedClass)]; static BaseClass* target; if (!target) { target = new(obj)DerivedClass(); } return target; } 47 x64 mov rax,qword ptr [1400089A0h] test rax,rax jne @1 lea rcx,[140008968h] mov qword ptr [rsp+40h],rcx call ??0DerivedClass@@QEAA@XZ nop mov qword ptr [1400089A0h],rax @1: ret
  • 48. Статические переменные функции C++ BaseClass* GetStaticE() { static char obj[sizeof(DerivedClass)]; static BaseClass* target; if (!target) { target = new(obj)DerivedClass(); } return target; } 48 ARM push {r3, r4, r5, lr} ldr r4, [pc, #20] ; @d1 ldr r0, [r4, #32] cbz r0, @1 pop {r3, r4, r5, pc} @1: adds r5, r4, #4 mov r0, r5 bl <DerivedClass::DerivedClass()> mov r0, r5 str r5, [r4, #32] pop {r3, r4, r5, pc} @d1: .word 0x00012d08
  • 49. Статические переменные функции C++ BaseClass* GetStaticE() { static char obj[sizeof(DerivedClass)]; static BaseClass* target; if (!target) { target = new(obj)DerivedClass(); } return target; } 49 AVR lds r24, 0x017E lds r25, 0x017F or r24, r25 brne @1 sts 0x0173, r1 sts 0x0172, r1 sts 0x0175, r1 sts 0x0174, r1 sts 0x0177, r1 sts 0x0176, r1 ldi r24, 0x3A ldi r25, 0x01 sts 0x0171, r25 sts 0x0170, r24 sts 0x0179, r1 sts 0x0178, r1 sts 0x017B, r1 sts 0x017A, r1 sts 0x017D, r1 sts 0x017C, r1 ldi r24, 0x70 ldi r25, 0x01 sts 0x017F, r25 sts 0x017E, r24 @1: lds r24, 0x017E lds r25, 0x017F ret
  • 50. Статические переменные функции C++ BaseClass* GetStaticE() { static char obj[sizeof(DerivedClass)]; static BaseClass* target; if (!target) { target = new(obj)DerivedClass(); } return target; } 50 PowerPC stwu r1,-16(r1) mflr r0 stw r0,20(r1) stw r31,12(r1) lis r31,6 stw r30,8(r1) lwz r0,- 27056(r31) cmpwi cr7,r0,0 beq- cr7,@1 lwz r0,20(r1) lwz r3,- 27056(r31) lwz r30,8(r1) lwz r31,12(r1) mtlr r0 addi r1,r1,16 blr lis r4,6 li r3,28 addi r4,r4,-25724 bl <operator new(unsigned int, void*)> mr r30,r3 bl <DerivedClass::DerivedClass( )> stw r30,-27056(r31) lwz r0,20(r1) lwz r30,8(r1) @1: lwz r3,-27056(r31) lwz r31,12(r1) mtlr r0 addi r1,r1,16 blr
  • 51. Статические переменные функции C++ BaseClass* GetStaticE() { static char obj[sizeof(DerivedClass)]; static BaseClass* target; if (!target) { target = new(obj)DerivedClass(); } return target; } 51 MicroBlaze imm -28663 lwi r3, r0, 28640 addik r1, r1, -28 beqid r3, @1 swi r15, r1, 0 lwi r15, r1, 0 rtsd r15, 8 addik r1, r1, 28 @1: imm -28663 addik r5, r0, 28644 imm -1 brlid r15, <DerivedClass::DerivedClass()> imm -28663 addik r3, r0, 28644 lwi r15, r1, 0 imm -28663 swi r3, r0, 28640
  • 52. Статические переменные функции C++ template<int X> Point GetStaticF() { static Point staticFPoint; return staticFPoint; } 52 x86 ??$GetStaticF@$00@test_6@@YA?AUPoint@@XZ: mov eax, [?staticFPoint@?1???$GetStaticF@$00@test_6@@YA?AUPoint@@XZ@4U2@A] mov edx,dword ptr ds:[407594h] ret ??$GetStaticF@$01@test_6@@YA?AUPoint@@XZ: mov eax, [?staticFPoint@?1???$GetStaticF@$01@test_6@@YA?AUPoint@@XZ@4U2@A] mov edx,dword ptr ds:[40759Ch] ret ??$GetStaticF@$02@test_6@@YA?AUPoint@@XZ: mov eax, [?staticFPoint@?1???$GetStaticF@$02@test_6@@YA?AUPoint@@XZ@4U2@A] mov edx,dword ptr ds:[4075A4h] ret
  • 53. Статические переменные функции C++ template<int X> Point GetStaticF() { static Point staticFPoint; return staticFPoint; } 53 x64 ??$GetStaticF@$00@test_6@@YA?AUPoint@@XZ: movups xmm0,xmmword ptr [?staticFPoint@?1???$GetStaticF@$00@test_6@@YA?AUPoint@@XZ@4U2@A] mov rax,rcx movups xmmword ptr [rcx],xmm0 ret ??$GetStaticF@$01@test_6@@YA?AUPoint@@XZ: movups xmm0,xmmword ptr [?staticFPoint@?1???$GetStaticF@$01@test_6@@YA?AUPoint@@XZ@4U2@A] mov rax,rcx movups xmmword ptr [rcx],xmm0 ret ??$GetStaticF@$02@test_6@@YA?AUPoint@@XZ: movups xmm0,xmmword ptr [?staticFPoint@?1???$GetStaticF@$02@test_6@@YA?AUPoint@@XZ@4U2@A] mov rax,rcx movups xmmword ptr [rcx],xmm0 ret
  • 54. Статические переменные функции C++ template<int X> Point GetStaticF() { static Point staticFPoint; return staticFPoint; } 54 ARM <Point test_6::GetStaticF<1>()>: movw r2, #11788 movt r2, #1 mov r3, r0 ldmia.w r2, {r0, r1} stmia.w r3, {r0, r1} mov r0, r3 bx lr nop <Point test_6::GetStaticF<2>()>: movw r2, #11780 movt r2, #1 mov r3, r0 ldmia.w r2, {r0, r1} stmia.w r3, {r0, r1} mov r0, r3 bx lr nop <Point test_6::GetStaticF<3>()>: movw r2, #11772 movt r2, #1 mov r3, r0 ldmia.w r2, {r0, r1} stmia.w r3, {r0, r1} mov r0, r3 bx lr nop
  • 55. Статические переменные функции C++ template<int X> Point GetStaticF() { static Point staticFPoint; return staticFPoint; } 55 AVR <Point test_6::GetStaticF<1>()>: lds r22, 0x0186 lds r23, 0x0187 lds r24, 0x0188 lds r25, 0x0189 ret <Point test_6::GetStaticF<2>()>: lds r22, 0x018A lds r23, 0x018B lds r24, 0x018C lds r25, 0x018D ret <Point test_6::GetStaticF<3>()>: lds r22, 0x018E lds r23, 0x018F lds r24, 0x0190 lds r25, 0x0191 ret
  • 56. Статические переменные функции C++ template<int X> Point GetStaticF() { static Point staticFPoint; return staticFPoint; } 56 PowerPC <Point test_6::GetStaticF<1>()>: lis r9,6 addi r9,r9,-26872 lwz r3,0(r9) lwz r4,4(r9) blr <Point test_6::GetStaticF<2>()>: lis r9,6 addi r9,r9,-26880 lwz r3,0(r9) lwz r4,4(r9) blr <Point test_6::GetStaticF<3>()>: lis r9,6 addi r9,r9,-26888 lwz r3,0(r9) lwz r4,4(r9) blr
  • 57. Статические переменные функции C++ template<int X> Point GetStaticF() { static Point staticFPoint; return staticFPoint; } 57 MicroBlaze <Point test_6::GetStaticF<1>()>: addk r3, r5, r0 imm -28663 lwi r4, r0, 29140 imm -28663 lwi r5, r0, 29144 swi r4, r3, 0 swi r5, r3, 4 rtsd r15, 8 <Point test_6::GetStaticF<2>()>: addk r3, r5, r0 imm -28663 lwi r4, r0, 29132 imm -28663 lwi r5, r0, 29136 swi r4, r3, 0 swi r5, r3, 4 rtsd r15, 8 <Point test_6::GetStaticF<3>()>: addk r3, r5, r0 imm -28663 lwi r4, r0, 29124 imm -28663 lwi r5, r0, 29128 swi r4, r3, 0 swi r5, r3, 4 rtsd r15, 8
  • 58. Исключения Реализация сильно зависит от компилятора и от операционной системы В основе лежат нетривиальные концепции Очень большой объём ассемблерного кода Оставим для самостоятельного изучения 58
  • 59. Итоги 1. Магии нет 2. Многое из сказанного - ложь ● примеры кода сильно упрощены ● приходилось принимать меры против оптимизаций 1. С++ - быстрый язык, потери производительности возникают в предсказуемых местах 2. Не бойтесь, но запаситесь терпением 59
  • 60. Спасибо за внимание! А теперь - вопросы! 60 Алексей Ткаченко, ОАО “Пеленг” tkachenko@peleng.by alexey.tkachenko@gmail.com