[libc-commits] [libc] [llvm] [libc] Add fixed point support to printf (PR #82707)
Michael Jones via libc-commits
libc-commits at lists.llvm.org
Mon Feb 26 14:37:26 PST 2024
================
@@ -0,0 +1,386 @@
+//===-- Fixed Point Converter for printf ------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_STDIO_PRINTF_CORE_FIXED_CONVERTER_H
+#define LLVM_LIBC_SRC_STDIO_PRINTF_CORE_FIXED_CONVERTER_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "src/__support/CPP/string_view.h"
+#include "src/__support/fixed_point/fx_bits.h"
+#include "src/__support/fixed_point/fx_rep.h"
+#include "src/__support/integer_to_string.h"
+#include "src/__support/libc_assert.h"
+#include "src/stdio/printf_core/converter_utils.h"
+#include "src/stdio/printf_core/core_structs.h"
+#include "src/stdio/printf_core/writer.h"
+
+#include <inttypes.h>
+#include <stddef.h>
+
+namespace LIBC_NAMESPACE {
+namespace printf_core {
+
+// This is just for assertions. It will be compiled out for release builds.
+LIBC_INLINE constexpr uint32_t const_ten_exp(uint32_t exponent) {
+ uint32_t result = 1;
+ LIBC_ASSERT(exponent < 11);
+ for (size_t i = 0; i < exponent; ++i)
+ result *= 10;
+
+ return result;
+}
+
+LIBC_INLINE int convert_fixed(Writer *writer, const FormatSection &to_conv) {
+ using SAStorageType = fixed_point::FXRep<short accum>::StorageType;
+ using AStorageType = fixed_point::FXRep<accum>::StorageType;
+ using LAStorageType = fixed_point::FXRep<long accum>::StorageType;
+ using SFStorageType = fixed_point::FXRep<short fract>::StorageType;
+ using FStorageType = fixed_point::FXRep<fract>::StorageType;
+ using LFStorageType = fixed_point::FXRep<long fract>::StorageType;
+
+ // Long accum should be the largest type, so we can store all the smaller
+ // numbers in things sized for it.
+ using LARep = fixed_point::FXRep<unsigned long accum>;
+ using StorageType = LARep::StorageType;
+
+ // All of the letters will be defined relative to variable a, which will be
+ // the appropriate case based on the name of the conversion. This converts any
+ // conversion name into the letter 'a' with the appropriate case.
+ const char a = (to_conv.conv_name & 32) | 'A';
+ FormatFlags flags = to_conv.flags;
+
+ bool is_negative;
+ int exponent;
+ StorageType integral;
+ StorageType fractional;
+
+ // TODO: See about simplifying this mess of a 3D matrix if statement.
+ // r = fract
+ // k = accum
+ // lowercase = signed
+ // uppercase = unsigned
+ // h = short
+ // l = long
+ // any other length modifier has no effect
+ if (to_conv.length_modifier == LengthModifier::h) {
+ // short types
+ if (to_conv.conv_name == 'r') {
+ auto fixed_bits = fixed_point::FXBits<short fract>(
+ static_cast<SFStorageType>(to_conv.conv_val_raw));
+ integral = fixed_bits.get_integral();
+ fractional = fixed_bits.get_fraction();
+ exponent = fixed_bits.get_exponent();
+ is_negative = fixed_bits.get_sign();
+ }
+ if (to_conv.conv_name == 'R') {
+ auto fixed_bits = fixed_point::FXBits<unsigned short fract>(
+ static_cast<SFStorageType>(to_conv.conv_val_raw));
+ integral = fixed_bits.get_integral();
+ fractional = fixed_bits.get_fraction();
+ exponent = fixed_bits.get_exponent();
+ is_negative = fixed_bits.get_sign();
+ }
+ if (to_conv.conv_name == 'k') {
+ auto fixed_bits = fixed_point::FXBits<short accum>(
+ static_cast<SAStorageType>(to_conv.conv_val_raw));
+ integral = fixed_bits.get_integral();
+ fractional = fixed_bits.get_fraction();
+ exponent = fixed_bits.get_exponent();
+ is_negative = fixed_bits.get_sign();
+ }
+ if (to_conv.conv_name == 'K') {
+ auto fixed_bits = fixed_point::FXBits<unsigned short accum>(
+ static_cast<SAStorageType>(to_conv.conv_val_raw));
+ integral = fixed_bits.get_integral();
+ fractional = fixed_bits.get_fraction();
+ exponent = fixed_bits.get_exponent();
+ is_negative = fixed_bits.get_sign();
+ }
+ } else if (to_conv.length_modifier == LengthModifier::l) {
+ // long types
+ if (to_conv.conv_name == 'r') {
+ auto fixed_bits = fixed_point::FXBits<long fract>(
+ static_cast<LFStorageType>(to_conv.conv_val_raw));
+ integral = fixed_bits.get_integral();
+ fractional = fixed_bits.get_fraction();
+ exponent = fixed_bits.get_exponent();
+ is_negative = fixed_bits.get_sign();
+ }
+ if (to_conv.conv_name == 'R') {
+ auto fixed_bits = fixed_point::FXBits<unsigned long fract>(
+ static_cast<LFStorageType>(to_conv.conv_val_raw));
+ integral = fixed_bits.get_integral();
+ fractional = fixed_bits.get_fraction();
+ exponent = fixed_bits.get_exponent();
+ is_negative = fixed_bits.get_sign();
+ }
+ if (to_conv.conv_name == 'k') {
+ auto fixed_bits = fixed_point::FXBits<long accum>(
+ static_cast<LAStorageType>(to_conv.conv_val_raw));
+ integral = fixed_bits.get_integral();
+ fractional = fixed_bits.get_fraction();
+ exponent = fixed_bits.get_exponent();
+ is_negative = fixed_bits.get_sign();
+ }
+ if (to_conv.conv_name == 'K') {
+ auto fixed_bits = fixed_point::FXBits<unsigned long accum>(
+ static_cast<LAStorageType>(to_conv.conv_val_raw));
+ integral = fixed_bits.get_integral();
+ fractional = fixed_bits.get_fraction();
+ exponent = fixed_bits.get_exponent();
+ is_negative = fixed_bits.get_sign();
+ }
+ } else {
+ // unspecified types
+ if (to_conv.conv_name == 'r') {
+ auto fixed_bits = fixed_point::FXBits<fract>(
+ static_cast<FStorageType>(to_conv.conv_val_raw));
+ integral = fixed_bits.get_integral();
+ fractional = fixed_bits.get_fraction();
+ exponent = fixed_bits.get_exponent();
+ is_negative = fixed_bits.get_sign();
+ }
+ if (to_conv.conv_name == 'R') {
+ auto fixed_bits = fixed_point::FXBits<unsigned fract>(
+ static_cast<FStorageType>(to_conv.conv_val_raw));
+ integral = fixed_bits.get_integral();
+ fractional = fixed_bits.get_fraction();
+ exponent = fixed_bits.get_exponent();
+ is_negative = fixed_bits.get_sign();
+ }
+ if (to_conv.conv_name == 'k') {
+ auto fixed_bits = fixed_point::FXBits<accum>(
+ static_cast<AStorageType>(to_conv.conv_val_raw));
+ integral = fixed_bits.get_integral();
+ fractional = fixed_bits.get_fraction();
+ exponent = fixed_bits.get_exponent();
+ is_negative = fixed_bits.get_sign();
+ }
+ if (to_conv.conv_name == 'K') {
+ auto fixed_bits = fixed_point::FXBits<unsigned accum>(
+ static_cast<AStorageType>(to_conv.conv_val_raw));
+ integral = fixed_bits.get_integral();
+ fractional = fixed_bits.get_fraction();
+ exponent = fixed_bits.get_exponent();
+ is_negative = fixed_bits.get_sign();
+ }
+ }
----------------
michaelrj-google wrote:
That doesn't solve my problem, we'd still need this terrible nested set of `if`s.
https://github.com/llvm/llvm-project/pull/82707
More information about the libc-commits
mailing list