আমি বিশ্বাস করি ও'নিলের পিসিজি পিআরএনজি বাস্তবায়নের সময় আমি জিসিসিতে একটি বাগ পেয়েছি। ( গডবোল্টের সংকলক এক্সপ্লোরার এর প্রাথমিক কোড )
, (আরডিআই-তে সংরক্ষিত ফলাফল) oldstate
দ্বারা গুণ করার পরে MULTIPLIER
, জিসিসি সেই ফলাফলটিকে INCREMENT
আরডিএক্সে যোগ করে না INCREMENT
, যা পরে র্যান্ড 32_ret.state এর রিটার্ন মান হিসাবে ব্যবহৃত হয়
একটি সর্বনিম্ন পুনরুত্পাদনযোগ্য উদাহরণ ( সংকলক এক্সপ্লোরার ):
#include <stdint.h>
struct retstruct {
uint32_t a;
uint64_t b;
};
struct retstruct fn(uint64_t input)
{
struct retstruct ret;
ret.a = 0;
ret.b = input * 11111111111 + 111111111111;
return ret;
}
উত্পন্ন সমাবেশ (জিসিসি 9.2, x86_64, -O3):
fn:
movabs rdx, 11111111111 # multiplier constant (doesn't fit in imm32)
xor eax, eax # ret.a = 0
imul rdi, rdx
movabs rdx, 111111111111 # add constant; one more 1 than multiplier
# missing add rdx, rdi # ret.b=... that we get with clang or older gcc
ret
# returns RDX:RAX = constant 111111111111 : 0
# independent of input RDI, and not using the imul result it just computed
মজার বিষয় হচ্ছে, প্রথম সদস্য হিসাবে uint64_t থাকার কাঠামোটি পরিবর্তন করে সঠিক কোড তৈরি করে যেমন উভয় সদস্যকে uint64_t হিসাবে পরিবর্তন করা হয়
x86-64 সিস্টেম ভি আরডিএক্স: আরএক্স-এ 16 বাইটের চেয়ে কম স্ট্রাক্ট রিটার্ন করে যখন তারা তুচ্ছভাবে অনুলিপিযোগ্য হয়। এই ক্ষেত্রে ২ য় সদস্য আরডিএক্সে রয়েছে কারণ উচ্চতর অর্ধেক RAX প্রান্তিককরণের জন্য প্যাডিং বা .b
যখন .a
সংকীর্ণ ধরণের হয়। ( sizeof(retstruct)
যে কোনও উপায়ে 16 টি; আমরা ব্যবহার করছি না __attribute__((packed))
তাই এটি অ্যালাইনফের সম্মান করে (uint64_t) = 8.)
এই কোডটিতে এমন কোনও অপরিজ্ঞিত আচরণ রয়েছে যা জিসিসিকে "ভুল" অ্যাসেম্বলিটি নির্গত করতে দেয়?
যদি তা না হয় তবে https://gcc.gnu.org/bugzilla/ এ এই প্রতিবেদন করা উচিত