PowerPC分支只有24位可用于目标偏移,因此如果文本部分太大,则一端的分支将无法到达另一端的目标.有一个更长的指令序列可以到达更远的目标(偏移量是32位而不是24位),但GCC默认不使用它,除非你通过它-mlongcall选项.但是,即使启用此选项,GCC仍会为某些功能生成短调,即operator new和operator delete
例如,给定此代码:
extern void foo();
int main(int argc, char** argv) {
foo();
new char;
}
Run Code Online (Sandbox Code Playgroud)
正常运行的GCC将生成程序集:
bl _Z3foov // void foo()
bl _Znwj // operator new(unsigned int)
Run Code Online (Sandbox Code Playgroud)
使用该-mlongcall选项运行GCC会生成:
lis r9, _Z3foov@ha
addi r9, r9, _Z3foov@l
mtctr r9
bctrl
bl _Znwj
Run Code Online (Sandbox Code Playgroud)
foo()正如预期的那样,前四个指令是一个长期调用,但调用operator new没有改变.对随机libc和libstdc ++函数的调用都按预期转换为长调用.为什么operator new和operator delete电话仍然最终作为bl指示?有没有办法迫使海湾合作委员会长期打电话?我在64位PowerPC Fedora机器上使用GCC 4.7.2(虽然我正在构建32位)
看起来 g++ 工具链在如何调用架构上 C++ 标准库的八个“可替换”函数方面存在某种错误,如果这些函数实际上没有被用户代码替换的话。
所有八个的便携式替代实现是:
#include <memory>
#include <cstdlib>
// May never return a null pointer.
void* operator new(std::size_t size) {
void* p = std::malloc(size, 1);
while (!p) {
std::new_handler handler = std::get_new_handler();
if (handler) {
handler();
} else {
throw std::bad_alloc();
}
// A handler is only allowed to return if it did something to make more
// memory available, so try again.
p = std::malloc(size, 1);
}
return p;
}
void operator delete(void* p) noexcept {
if (p) std::free(p);
}
void* operator new(std::size_t size, const std::nothrow_t&) noexcept {
void* p = nullptr;
try {
p = operator new(size);
} catch(...) {}
return p;
}
void operator delete(void* p, const std::nothrow_t&) noexcept {
operator delete(p);
}
// May never return a null pointer.
void* operator new[](std::size_t size) {
return operator new(size);
}
void operator delete[](void* p) noexcept {
operator delete(p);
}
void* operator new[](std::size_t size, const std::nothrow_t& nt) noexcept {
return operator new(size, nt);
}
void operator delete[](void* p, const std::nothrow_t& nt) noexcept {
operator delete(p, nt);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
843 次 |
| 最近记录: |