GCC拒绝在PowerPC上发出长期调用new / delete的操作

时间:2013-03-11 22:33:31

标签: c++ gcc powerpc

PowerPC分支只有24位可用于目标偏移,因此如果文本部分太大,则一端的分支将无法到达另一端的目标。有一个更长的指令序列可以到达更远的目标(偏移量是32位而不是24位),但GCC默认不使用它,除非你传递-mlongcall选项。但是,即使启用此选项,GCC仍会为某些功能生成短暂呼叫,即operator newoperator delete

例如,给定此代码:

extern void foo();

int main(int argc, char** argv) {
    foo();
    new char;
}

GCC的正常运行将生成程序集:

bl _Z3foov // void foo()
bl _Znwj   // operator new(unsigned int)

使用-mlongcall选项运行GCC会生成:

lis r9, _Z3foov@ha
addi r9, r9, _Z3foov@l
mtctr r9
bctrl
bl _Znwj

前四条指令是对foo()的长时间调用,正如预期的那样,但对operator new的调用未发生变化。对随机libc和libstdc ++函数的调用都按预期转换为长调用。为什么operator newoperator delete来电仍以bl指令结尾?有没有办法迫使海湾合作委员会长期打电话?我在64位PowerPC Fedora机器上使用GCC 4.7.2(虽然我正在构建32位)

2 个答案:

答案 0 :(得分:3)

似乎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);
}

答案 1 :(得分:0)

如果我们可以在#pragma long_calls下定义这个函数或者在这个函数中声明long-call属性,我们也可以强制GCC对它们进行长调用。 结帐GCC选项。