[libc] [llvm] [libc] Add fixed point support to printf (PR #82707)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Feb 27 09:41:38 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 (uint32_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') {
----------------
lntue wrote:
nit: I wonder if using a `switch` for the inner `if`'s would make it easier to read / separate cases for the outer `if`.
https://github.com/llvm/llvm-project/pull/82707
More information about the llvm-commits
mailing list