2016-05-28 2 views
0

Я пытаюсь скомпилировать webrtc на 32bit centos6 и получить следующую ошибку. но это хорошо работает на 64-битных центрах. Кто-нибудь может мне помочь?ошибка: операнд «asm» имеет невозможные ограничения при использовании gcc 32bit

row_gcc.cc:3574:4: error: ‘asm’ operand has impossible constraints 

Команда компиляции:

CXX obj/chromium/src/third_party/libyuv/source/libyuv.row_gcc.o 
FAILED: obj/chromium/src/third_party/libyuv/source/libyuv.row_gcc.o 
c++ -MMD -MF obj/chromium/src/third_party/libyuv/source/libyuv.row_gcc.o.d 
-DV8_DEPRECATION_WARNINGS -D_FILE_OFFSET_BITS=64 -DCHROMIUM_BUILD 
-DUI_COMPOSITOR_IMAGE_TRANSPORT -DUSE_AURA=1 -DUSE_PANGO=1 -DUSE_CAIRO=1 
-DUSE_DEFAULT_RENDER_THEME=1 -DUSE_LIBJPEG_TURBO=1 -DUSE_X11=1 
-DUSE_CLIPBOARD_AURAX11=1 -DENABLE_WEBRTC=1 -DENABLE_MEDIA_ROUTER=1 
-DENABLE_PEPPER_CDMS -DENABLE_NOTIFICATIONS -DENABLE_TOPCHROME_MD=1 
-DUSE_UDEV -DFIELDTRIAL_TESTING_ENABLED -DENABLE_TASK_MANAGER=1 
-DENABLE_EXTENSIONS=1 -DENABLE_PDF=1 -DENABLE_PLUGINS=1 
-DENABLE_SESSION_SERVICE=1 -DENABLE_THEMES=1 -DENABLE_PRINTING=1 
-DENABLE_BASIC_PRINTING=1 -DENABLE_PRINT_PREVIEW=1 -DENABLE_SPELLCHECK=1 
-DENABLE_CAPTIVE_PORTAL_DETECTION=1 -DENABLE_APP_LIST=1 
-DENABLE_SETTINGS_APP=1 -DENABLE_SUPERVISED_USERS=1 -DENABLE_MDNS=1 
-DENABLE_SERVICE_DISCOVERY=1 -DV8_USE_EXTERNAL_STARTUP_DATA 
-DFULL_SAFE_BROWSING -DSAFE_BROWSING_CSD -DSAFE_BROWSING_DB_LOCAL 
-DHAVE_JPEG -DUSE_LIBPCI=1 -DUSE_GLIB=1 -DUSE_NSS_CERTS=1 
-D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS 
-DDYNAMIC_ANNOTATIONS_ENABLED=1 -DWTF_USE_DYNAMIC_ANNOTATIONS=1 
-D_DEBUG -Igen 
-I../../chromium/src/third_party/libyuv/include 
-I../../chromium/src/third_party/libyuv 
-I../../chromium/src/third_party/libjpeg_turbo -fstack-protector 
--param=ssp-buffer-size=4 -pthread -fno-strict-aliasing -Wall -Wno-extra 
-Wno-unused-parameter -Wno-missing-field-initializers -fvisibility=hidden 
-pipe -fPIC 
-B/home/test/webrtc-checkout/src/third_party/binutils/Linux_ia32/Release/bin 
-Wno-unused-local-typedefs -msse2 -mfpmath=sse -mmmx -m32 -O0 -g 
-funwind-tables -fno-exceptions -fno-rtti -fno-threadsafe-statics 
-fvisibility-inlines-hidden 
-std=gnu++11 -Wno-narrowing 
-c ../../chromium/src/third_party/libyuv/source/row_gcc.cc 
-o obj/chromium/src/third_party/libyuv/source/libyuv.row_gcc.o 
../../chromium/src/third_party/libyuv/source/row_gcc.cc: 
In function ‘void libyuv::BlendPlaneRow_SSSE3(const uint8*, 
const uint8*, const uint8*, uint8*, int)’: 
../../chromium/src/third_party/libyuv/source/row_gcc.cc:3574:4: 
error: ‘asm’ operand has impossible constraints 

версия GCC: 4.8.5

в версии: GNU ассемблере (GNU Binutils) 2.26.20160125

third_party/binutils/Linux_ia32/Release/bin/as --version 
GNU assembler (GNU Binutils) 2.26.20160125 
Copyright (C) 2015 Free Software Foundation, Inc. 
This program is free software; you may redistribute it under the terms of 
the GNU General Public License version 3 or later. 
This program has absolutely no warranty. 
This assembler was configured for a target of `i686-pc-linux-gnu'. 

Код в chromium/src/third_party/libyuv/source/row_gcc.cc:

void BlendPlaneRow_SSSE3(const uint8* src0, const uint8* src1, 
        const uint8* alpha, uint8* dst, int width) { 
asm volatile (
"pcmpeqb %%xmm5,%%xmm5     \n" 
"psllw  $0x8,%%xmm5     \n" 
"mov  $0x80808080,%%eax    \n" 
"movd  %%eax,%%xmm6     \n" 
"pshufd  $0x0,%%xmm6,%%xmm6    \n" 
"mov  $0x807f807f,%%eax    \n" 
"movd  %%eax,%%xmm7     \n" 
"pshufd  $0x0,%%xmm7,%%xmm7    \n" 
"sub  %2,%0       \n" 
"sub  %2,%1       \n" 
"sub  %2,%3       \n" 

// 8 pixel loop. 
LABELALIGN 
"1:           \n" 
"movq  (%2),%%xmm0     \n" 
"punpcklbw %%xmm0,%%xmm0     \n" 
"pxor  %%xmm5,%%xmm0     \n" 
"movq  (%0,%2,1),%%xmm1    \n" 
"movq  (%1,%2,1),%%xmm2    \n" 
"punpcklbw %%xmm2,%%xmm1     \n" 
"psubb  %%xmm6,%%xmm1     \n" 
"pmaddubsw %%xmm1,%%xmm0     \n" 
"paddw  %%xmm7,%%xmm0     \n" 
"psrlw  $0x8,%%xmm0     \n" 
"packuswb %%xmm0,%%xmm0     \n" 
"movq  %%xmm0,(%3,%2,1)    \n" 
"lea  0x8(%2),%2      \n" 
"sub  $0x8,%4      \n" 
"jg  1b        \n" 
: "+r"(src0),  // %0 
"+r"(src1),  // %1 
"+r"(alpha),  // %2 
"+r"(dst),  // %3 
"+r"(width)  // %4 
:: "memory", "cc", "eax", "xmm0", "xmm1", "xmm2", "xmm5", "xmm6", "xmm7" 
); 
+1

Я не вижу в этом ничего плохого. Однако вы используете много регистров. Учитывая, что это работает на x64, мне интересно, закончились ли вы? Для эксперимента, что произойдет, если вы нажмете eax перед движением $ 0x80808080, поместите его после перемещения xmm7 и удалите его из клобелей? Это даст gcc еще 1 общий регистр. Что-то попробовать, так или иначе. –

+0

В качестве альтернативы (или, возможно, дополнительно) вы также можете изменить ширину от «+ r» до «+ m». –

+1

Давид прав, и, в частности, libyuv предполагает наличие 5 регистров. Обычно эти регистры общего назначения доступны _EAX_, _EBX_, _ECX_, _EDX_, _ESI_, _EDI_ и _EBP_. _EAX_ находится в списке clobber настолько непригодным для использования. Поскольку вы не опускаете указатели фрейма стека, _EBP_ недоступен. Потому что он строится с помощью '-fPIC'_EBX_, недоступен. По существу, в этой 32-битной сборке доступны только доступные регистры _ECX_, _EDX_, _ESI_, _EDI_. 5 регистров необходимы, 4 доступны. Можете попробовать перекомпилировать все это снова с помощью '-fomit-frame-pointer' или даже' -O3' isntead '-O0' –

ответ

3

Как и Дэвид Вольфредд, проблема заключается в том, что у вас закончились регистры. Существует 8 регистров общего назначения, один из которых - ESP, указатель стека и никогда не может использоваться для удовлетворения ограничений. Еще два регистра, EBP и EBX также не могут использоваться для удовлетворения ограничений из-за параметров, которые вы компилируете. Поскольку вы компилируете без оптимизации, регистр EBP зарезервирован для указателя кадра, и поскольку вы используете флаг -fPIC, регистр EBX зарезервирован для доступа к GOT (Global Object Table).

Чтобы оставить пять регистров, которые могут использоваться для удовлетворения ограничений регистра, EAX, ECX, EDX, ESI и EDI. Однако ваш оператор asm clobbers EAX, так что его нельзя использовать, оставляя только четыре регистра. Оператор asm имеет пять операндов с ограничениями регистра, что означает, что для него требуется пять отдельных регистров, но для компилятора доступно только четыре. Таким образом, ограничения невозможно удовлетворить.

Простым решением было бы освободить регистр, удалив использование EAX в инструкции asm. Этот регистр используется для загрузки двух разных постоянных значений в два разных регистра XMM. Вместо этого можно загрузить константы непосредственно из памяти. Например:

void BlendPlaneRow_SSSE3(const uint8* src0, const uint8* src1, 
        const uint8* alpha, uint8* dst, int width) { 
     static unsigned const __attribute__((aligned(4))) xmm6[4] = { 
       0x80808080, 0x80808080, 0x80808080, 0x80808080 
     }; 
     static unsigned const __attribute__((aligned(4))) xmm7[4] = { 
       0x807f807f, 0x807f807f, 0x807f807f, 0x807f807f 
     }; 

asm volatile (
"pcmpeqb %%xmm5,%%xmm5     \n" 
"psllw  $0x8,%%xmm5     \n" 
"movaps  %5,%%xmm6      \n" 
"movaps  %6,%%xmm7      \n" 
"sub  %2,%0       \n" 
"sub  %2,%1       \n" 
"sub  %2,%3       \n" 

// 8 pixel loop. 
LABELALIGN 
"1:           \n" 
"movq  (%2),%%xmm0     \n" 
"punpcklbw %%xmm0,%%xmm0     \n" 
"pxor  %%xmm5,%%xmm0     \n" 
"movq  (%0,%2,1),%%xmm1    \n" 
"movq  (%1,%2,1),%%xmm2    \n" 
"punpcklbw %%xmm2,%%xmm1     \n" 
"psubb  %%xmm6,%%xmm1     \n" 
"pmaddubsw %%xmm1,%%xmm0     \n" 
"paddw  %%xmm7,%%xmm0     \n" 
"psrlw  $0x8,%%xmm0     \n" 
"packuswb %%xmm0,%%xmm0     \n" 
"movq  %%xmm0,(%3,%2,1)    \n" 
"lea  0x8(%2),%2      \n" 
"sub  $0x8,%4      \n" 
"jg  1b        \n" 
: "+r"(src0),  // %0 
"+r"(src1),  // %1 
"+r"(alpha),  // %2 
"+r"(dst),  // %3 
"+r"(width)  // %4 
: "m" (xmm6), 
"m" (xmm7) 
: "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm5", "xmm6", "xmm7" 
); 
} 

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

+1

Или просто попросите константы быть в xmm regs. Вы можете использовать ограничение '' x "' со скалярным целочисленным значением, а компилятор будет 'movd' или' movq' для вас. –

+0

@PeterCordes Не знал, что, хотя я решил, что загрузка константы из памяти будет быстрее, чем три инструкции, которые она заменяет в любом случае. –

+0

Наверное, хорошо, да. Риск промаха в кеше уравновешивается уменьшением отпечатка кэш-памяти. Тем не менее, '0x80808080' может быть [сгенерирован« на лету »с еще двумя инструкциями] (http://stackoverflow.com/questions/35085059/what-are-the-best-instruction-sequences-to-generate-vector-constants -on-the-fly): SSSE3 'pabsb% xmm5,% xmm6' (0x010101 ...), затем сдвиг влево xmm6, чтобы поместить эти одиночные биты в верхнее положение. –

Смежные вопросы