Skip to content

Commit a64d3cf

Browse files
added bitfield
1 parent 8d98213 commit a64d3cf

File tree

5 files changed

+132
-1
lines changed

5 files changed

+132
-1
lines changed

include/mrdox/Metadata/BitField.hpp

+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
//
2+
// This is a derivative work. originally part of the LLVM Project.
3+
// Licensed under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
// Copyright (c) 2023 Klemens D. Morgenstern
8+
//
9+
//
10+
// Official repository: https://github.com/cppalliance/mrdox
11+
//
12+
13+
#ifndef MRDOX_METADATA_BITFIELD_HPP
14+
#define MRDOX_METADATA_BITFIELD_HPP
15+
16+
#include <cstdint>
17+
#include <limits>
18+
#include <type_traits>
19+
20+
namespace clang {
21+
namespace mrdox {
22+
23+
24+
constexpr std::uint32_t makeMask(unsigned char Offset,
25+
unsigned char Size)
26+
{
27+
auto init = std::numeric_limits<std::uint32_t>::max();
28+
auto offset = init << Offset;
29+
auto rest = init >>= (sizeof(std::uint32_t) * 8) - (Offset + Size);
30+
return offset & rest;
31+
}
32+
33+
34+
template<unsigned char Offset,
35+
unsigned char Size = 1u,
36+
typename T = std::uint32_t>
37+
struct BitField
38+
{
39+
using underlying_type = std::uint32_t;
40+
underlying_type value;
41+
42+
constexpr static underlying_type mask = makeMask(Offset, Size);
43+
constexpr static underlying_type offset = Offset;
44+
constexpr static underlying_type size = Size;
45+
46+
constexpr T get() const noexcept
47+
{
48+
constexpr underlying_type simple_mask = makeMask(0u, Offset + Size);
49+
auto val = value & simple_mask;
50+
51+
if constexpr (std::is_signed<T>::value && (Size + Offset) < (sizeof(underlying_type) * 8u))
52+
{
53+
constexpr underlying_type minus = static_cast<underlying_type>(1) << (Size + Offset);
54+
if ((val & minus) != static_cast<underlying_type>(0))
55+
val |= ~simple_mask; //2s complement - I think
56+
}
57+
val >>= Offset;
58+
return static_cast<T>(val);
59+
}
60+
61+
constexpr operator T () const noexcept
62+
{
63+
return get();
64+
}
65+
66+
constexpr void set(T val) noexcept
67+
{
68+
auto update = (static_cast<underlying_type>(val) << Offset) & mask;
69+
value = (value & ~mask) | update;
70+
}
71+
72+
constexpr T operator=(T val) noexcept { set(val); return val;}
73+
};
74+
75+
template<unsigned char Offset>
76+
using BitFlag = BitField<Offset, 1u, bool>;
77+
78+
using BitFieldFullValue = BitField<0, 32>;
79+
80+
}
81+
}
82+
83+
#endif //MRDOX_METADATA_BITFIELD_HPP

include/mrdox/MetadataFwd.hpp

+7
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,13 @@ struct TypedefInfo;
4949
struct VarInfo;
5050
struct VerbatimBlock;
5151

52+
53+
template<unsigned char Offset,
54+
unsigned char Size,
55+
typename T>
56+
struct BitField;
57+
using BitFieldFullValue = BitField<0, 32, std::uint32_t>;
58+
5259
} // mrdox
5360
} // clang
5461

source/api/AST/BitcodeWriter.cpp

+19-1
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,24 @@ emitRecord(
552552
Stream.EmitRecordWithAbbrev(Abbrevs.get(ID), Record);
553553
}
554554

555+
556+
// Bits
557+
void
558+
BitcodeWriter::
559+
emitRecord(
560+
std::initializer_list<BitFieldFullValue> values,
561+
RecordId ID)
562+
{
563+
Assert(RecordIdNameMap[ID]);
564+
Assert(RecordIdNameMap[ID].Abbrev == &Integer32ArrayAbbrev);
565+
if (!prepRecordData(ID, true))
566+
return;
567+
Record.push_back(values.size());
568+
for(std::uint32_t value : values)
569+
Record.push_back(value);
570+
Stream.EmitRecordWithAbbrev(Abbrevs.get(ID), Record);
571+
}
572+
555573
// SymbolIDs
556574
void
557575
BitcodeWriter::
@@ -776,7 +794,7 @@ emitBlock(
776794
emitSymbolPart(I);
777795
emitRecord(I.Access, FUNCTION_ACCESS);
778796
emitRecord(I.IsMethod, FUNCTION_IS_METHOD);
779-
emitRecord(FUNCTION_BITS, I.specs0, I.specs1);
797+
emitRecord({I.specs0.raw, I.specs1.raw}, FUNCTION_BITS);
780798
emitBlock(I.Parent, FieldId::F_parent);
781799
emitBlock(I.ReturnType);
782800
for (const auto& N : I.Params)

source/api/AST/BitcodeWriter.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
namespace clang {
3636
namespace mrdox {
3737

38+
3839
class BitcodeWriter
3940
{
4041
public:
@@ -94,6 +95,7 @@ class BitcodeWriter
9495
void emitRecord(Location const& Loc, RecordId ID);
9596
void emitRecord(bool Value, RecordId ID);
9697
void emitRecord(TemplateInfo const& Templ);
98+
void emitRecord(std::initializer_list<BitFieldFullValue> values, RecordId ID);
9799
//void emitRecord(Reference const& Ref, RecordId ID);
98100

99101
bool prepRecordData(RecordId ID, bool ShouldEmit = true);

source/api/AST/DecodeRecord.hpp

+21
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,27 @@ decodeRecord(
266266
return llvm::Error::success();
267267
}
268268

269+
template<std::size_t N>
270+
inline
271+
llvm::Error
272+
decodeRecord(
273+
Record const& R,
274+
std::array<BitFieldFullValue*, N> values,
275+
llvm::StringRef Blob)
276+
{
277+
auto n = R[0];
278+
if(n != N)
279+
return makeError("wrong size(", n, ") for Bitfields[", N, "]");
280+
for(std::size_t i = 0; i < N; ++i)
281+
{
282+
auto const v = R[i + 1];
283+
if(v > (std::numeric_limits<std::uint32_t>::max)())
284+
return makeError(v, " is out of range for Bits");
285+
*values[i] = v;
286+
}
287+
return llvm::Error::success();
288+
}
289+
269290
} // mrdox
270291
} // clang
271292

0 commit comments

Comments
 (0)