LLVM: сделать LLVMFP128Type из длинного двойного
В LLVM есть LLVMFP128Type
, хотя я не могу понять, как преобразовать реальный long double
в LLVMValueRef
типа LLVMFP128Type
прямо.
Я могу сделать следующее (с double
):
LLVMValueRef var = LLVMBuildAlloca(
builder,
LLVMDoubleTypeInContext(ctx),
"x"
);
double num = 3.1415;
LLVMBuildStore(
builder,
LLVMConstReal(
LLVMDoubleTypeInContext(ctx),
num
),
var
);
Создание следующего LLVM IR:
%x = alloca double
store double 3.141500e+00, double* %x
Но как мне сделать то же самое для long double
? E стьLLVMConstRealOfString
функция, которая принимает константу с плавающей запятой из строки, хотя я считаю неэффективным преобразовывать в строку и из строки, используя что-то вроде sprintf
:
LLVMValueRef var = LLVMBuildAlloca(
builder,
LLVMFP128TypeInContext(ctx),
"x"
);
// long double num = 3.1415L;
LLVMBuildStore(
builder,
LLVMConstRealOfString(
LLVMFP128TypeInContext(ctx),
"3.1415" // would have to sprintf `num`
),
var
);
Дает следующий (желаемый) LLVM IR:
%x = alloca fp128
store fp128 0xLE978D4FDF3B645A24000921CAC083126, fp128* %x
Как я могу получить желаемые результаты (нижний пример) с простотой первого примера?
1 ответ
Я не знаю о тех LLVMBuildStore
но GCC, ICC и Clang уже есть __float128
как расширение, так что вы можете просто использовать его. __float128 x = 3.1415;
приводит к следующему LLVM IR
%7 = load fp128*, fp128** %4, align 8, !dbg !22
store fp128 0xLF0000000000000004000921CAC083126, fp128* %7, align 16, !dbg !23
Демонстрация в Compiler Explorer
по факту long double
отображается на __float128
для большинства современных архитектур. В x86 есть аппаратная поддержка повышенной точности, поэтому она отображается на__float80
и вы можете использовать -mlong-double-128
возможность сделать его типом IEEE-754 binary128, т.е.__float128
. На PowerPClong double
по умолчанию использует двойную двойную арифметику, и вы можете использовать -mabi=ieeelongdouble
чтобы получить тот же эффект, что и выше