Skip to content

Commit 0a60c4c

Browse files
authored
[Support] Add signed operations to DataExtractor (#147261)
This is motivated by the [SFrame format](https://discourse.llvm.org/t/rfc-adding-sframe-support-to-llvm/86900), which contains several signed fields. Having explicit signed operations makes the parsing code read better and avoids potential surprises if e.g. a "signed" uint8_t value is converted ta greater width.
1 parent 54bd936 commit 0a60c4c

File tree

3 files changed

+67
-4
lines changed

3 files changed

+67
-4
lines changed

llvm/include/llvm/Support/DataExtractor.h

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,18 @@ class DataExtractor {
407407
getU8(C, Dst.data(), Count);
408408
}
409409

410+
/// Extract a int8_t value from \a *OffsetPtr. In case of an extraction error,
411+
/// or if error is already set, zero is returned and the offset is left
412+
/// unmodified.
413+
int8_t getS8(uint64_t *OffsetPtr, Error *Err = nullptr) const {
414+
return static_cast<int8_t>(getU8(OffsetPtr, Err));
415+
}
416+
417+
/// Extract a int8_t value from \a *OffsetPtr. In case of an extraction error,
418+
/// or if the cursor is already in an error state, zero is returned and the
419+
/// offset is left unmodified.
420+
int8_t getS8(Cursor &C) const { return static_cast<int8_t>(getU8(C)); }
421+
410422
//------------------------------------------------------------------
411423
/// Extract a uint16_t value from \a *offset_ptr.
412424
///
@@ -462,6 +474,18 @@ class DataExtractor {
462474
LLVM_ABI uint16_t *getU16(uint64_t *offset_ptr, uint16_t *dst,
463475
uint32_t count) const;
464476

477+
/// Extract a int16_t value from \a *OffsetPtr. In case of an extraction
478+
/// error, or if error is already set, zero is returned and the offset is left
479+
/// unmodified.
480+
int16_t getS16(uint64_t *OffsetPtr, Error *Err = nullptr) const {
481+
return static_cast<int16_t>(getU16(OffsetPtr, Err));
482+
}
483+
484+
/// Extract a int16_t value from \a *OffsetPtr. In case of an extraction
485+
/// error, or if the cursor is already in an error state, zero is returned and
486+
/// the offset is left unmodified.
487+
int16_t getS16(Cursor &C) const { return static_cast<int16_t>(getU16(C)); }
488+
465489
/// Extract a 24-bit unsigned value from \a *offset_ptr and return it
466490
/// in a uint32_t.
467491
///
@@ -543,6 +567,18 @@ class DataExtractor {
543567
LLVM_ABI uint32_t *getU32(uint64_t *offset_ptr, uint32_t *dst,
544568
uint32_t count) const;
545569

570+
/// Extract a int32_t value from \a *OffsetPtr. In case of an extraction
571+
/// error, or if error is already set, zero is returned and the offset is left
572+
/// unmodified.
573+
int32_t getS32(uint64_t *OffsetPtr, Error *Err = nullptr) const {
574+
return static_cast<int32_t>(getU32(OffsetPtr, Err));
575+
}
576+
577+
/// Extract a int32_t value from \a *OffsetPtr. In case of an extraction
578+
/// error, or if the cursor is already in an error state, zero is returned and
579+
/// the offset is left unmodified.
580+
int32_t getS32(Cursor &C) const { return static_cast<int32_t>(getU32(C)); }
581+
546582
/// Extract a uint64_t value from \a *offset_ptr.
547583
///
548584
/// Extract a single uint64_t from the binary data at the offset
@@ -596,6 +632,18 @@ class DataExtractor {
596632
LLVM_ABI uint64_t *getU64(uint64_t *offset_ptr, uint64_t *dst,
597633
uint32_t count) const;
598634

635+
/// Extract a int64_t value from \a *OffsetPtr. In case of an extraction
636+
/// error, or if error is already set, zero is returned and the offset is left
637+
/// unmodified.
638+
int64_t getS64(uint64_t *OffsetPtr, Error *Err = nullptr) const {
639+
return static_cast<int64_t>(getU64(OffsetPtr, Err));
640+
}
641+
642+
/// Extract a int64_t value from \a *OffsetPtr. In case of an extraction
643+
/// error, or if the cursor is already in an error state, zero is returned and
644+
/// the offset is left unmodified.
645+
int64_t getS64(Cursor &C) const { return static_cast<int64_t>(getU64(C)); }
646+
599647
/// Extract a signed LEB128 value from \a *offset_ptr.
600648
///
601649
/// Extracts an signed LEB128 number from this object's data

llvm/lib/Support/DataExtractor.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -142,13 +142,13 @@ int64_t
142142
DataExtractor::getSigned(uint64_t *offset_ptr, uint32_t byte_size) const {
143143
switch (byte_size) {
144144
case 1:
145-
return (int8_t)getU8(offset_ptr);
145+
return getS8(offset_ptr);
146146
case 2:
147-
return (int16_t)getU16(offset_ptr);
147+
return getS16(offset_ptr);
148148
case 4:
149-
return (int32_t)getU32(offset_ptr);
149+
return getS32(offset_ptr);
150150
case 8:
151-
return (int64_t)getU64(offset_ptr);
151+
return getS64(offset_ptr);
152152
}
153153
llvm_unreachable("getSigned unhandled case!");
154154
}

llvm/unittests/Support/DataExtractorTest.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,15 +78,30 @@ TEST(DataExtractorTest, SignedNumbers) {
7878

7979
EXPECT_EQ(-128, DE.getSigned(&offset, 1));
8080
EXPECT_EQ(1U, offset);
81+
offset = 0;
82+
EXPECT_EQ(-128, DE.getS8(&offset));
83+
EXPECT_EQ(1U, offset);
84+
8185
offset = 0;
8286
EXPECT_EQ(-32624, DE.getSigned(&offset, 2));
8387
EXPECT_EQ(2U, offset);
88+
offset = 0;
89+
EXPECT_EQ(-32624, DE.getS16(&offset));
90+
EXPECT_EQ(2U, offset);
91+
8492
offset = 0;
8593
EXPECT_EQ(-2137980929, DE.getSigned(&offset, 4));
8694
EXPECT_EQ(4U, offset);
95+
offset = 0;
96+
EXPECT_EQ(-2137980929, DE.getS32(&offset));
97+
EXPECT_EQ(4U, offset);
98+
8799
offset = 0;
88100
EXPECT_EQ(-9182558167379214336LL, DE.getSigned(&offset, 8));
89101
EXPECT_EQ(8U, offset);
102+
offset = 0;
103+
EXPECT_EQ(-9182558167379214336LL, DE.getS64(&offset));
104+
EXPECT_EQ(8U, offset);
90105
}
91106

92107
TEST(DataExtractorTest, Strings) {

0 commit comments

Comments
 (0)