llvm.org GIT mirror llvm / fa690d4
Change encodeU/SLEB128 to pad to certain number of bytes Previously the 'Padding' argument was the number of padding bytes to add. However most callers that use 'Padding' know how many overall bytes they need to write. With the previous code this would mean encoding the LEB once to find out how many bytes it would occupy and then using this to calulate the 'Padding' value. See: https://reviews.llvm.org/D36595 Differential Revision: https://reviews.llvm.org/D37494 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@313393 91177308-0d34-0410-b5e6-96231b3b80d8 Sam Clegg 1 year, 11 months ago
9 changed file(s) with 106 addition(s) and 87 deletion(s). Raw diff Collapse all Expand all
486486 void EmitSLEB128(int64_t Value, const char *Desc = nullptr) const;
487487
488488 /// Emit the specified unsigned leb128 value.
489 void EmitULEB128(uint64_t Value, const char *Desc = nullptr,
490 unsigned PadTo = 0) const;
489 void EmitULEB128(uint64_t Value, const char *Desc = nullptr) const;
490
491 /// Emit the specified unsigned leb128 value padded to a specific number
492 /// bytes
493 void EmitPaddedULEB128(uint64_t Value, unsigned PadTo,
494 const char *Desc = nullptr) const;
491495
492496 /// Emit a .byte 42 directive that corresponds to an encoding. If verbose
493497 /// assembly output is enabled, we output comments describing the encoding.
577577
578578 /// \brief Special case of EmitULEB128Value that avoids the client having to
579579 /// pass in a MCExpr for constant integers.
580 void EmitULEB128IntValue(uint64_t Value, unsigned Padding = 0);
580 void EmitULEB128IntValue(uint64_t Value);
581
582 /// \brief Like EmitULEB128Value but pads the output to specific number of
583 /// bytes.
584 void EmitPaddedULEB128IntValue(uint64_t Value, unsigned PadTo);
581585
582586 /// \brief Special case of EmitSLEB128Value that avoids the client having to
583587 /// pass in a MCExpr for constant integers.
2020
2121 /// Utility function to encode a SLEB128 value to an output stream.
2222 inline void encodeSLEB128(int64_t Value, raw_ostream &OS,
23 unsigned Padding = 0) {
23 unsigned PadTo = 0) {
24 bool More;
25 unsigned Count = 0;
26 do {
27 uint8_t Byte = Value & 0x7f;
28 // NOTE: this assumes that this signed shift is an arithmetic right shift.
29 Value >>= 7;
30 More = !((((Value == 0 ) && ((Byte & 0x40) == 0)) ||
31 ((Value == -1) && ((Byte & 0x40) != 0))));
32 Count++;
33 if (More || Count < PadTo)
34 Byte |= 0x80; // Mark this byte to show that more bytes will follow.
35 OS << char(Byte);
36 } while (More);
37
38 // Pad with 0x80 and emit a terminating byte at the end.
39 if (Count < PadTo) {
40 uint8_t PadValue = Value < 0 ? 0x7f : 0x00;
41 for (; Count < PadTo - 1; ++Count)
42 OS << char(PadValue | 0x80);
43 OS << char(PadValue);
44 }
45 }
46
47 /// Utility function to encode a SLEB128 value to a buffer. Returns
48 /// the length in bytes of the encoded value.
49 inline unsigned encodeSLEB128(int64_t Value, uint8_t *p, unsigned PadTo = 0) {
50 uint8_t *orig_p = p;
51 unsigned Count = 0;
2452 bool More;
2553 do {
2654 uint8_t Byte = Value & 0x7f;
2856 Value >>= 7;
2957 More = !((((Value == 0 ) && ((Byte & 0x40) == 0)) ||
3058 ((Value == -1) && ((Byte & 0x40) != 0))));
31 if (More || Padding != 0)
32 Byte |= 0x80; // Mark this byte to show that more bytes will follow.
33 OS << char(Byte);
34 } while (More);
35
36 // Pad with 0x80 and emit a terminating byte at the end.
37 if (Padding != 0) {
38 uint8_t PadValue = Value < 0 ? 0x7f : 0x00;
39 for (; Padding != 1; --Padding)
40 OS << char(PadValue | 0x80);
41 OS << char(PadValue);
42 }
43 }
44
45 /// Utility function to encode a SLEB128 value to a buffer. Returns
46 /// the length in bytes of the encoded value.
47 inline unsigned encodeSLEB128(int64_t Value, uint8_t *p, unsigned Padding = 0) {
48 uint8_t *orig_p = p;
49 bool More;
50 do {
51 uint8_t Byte = Value & 0x7f;
52 // NOTE: this assumes that this signed shift is an arithmetic right shift.
53 Value >>= 7;
54 More = !((((Value == 0 ) && ((Byte & 0x40) == 0)) ||
55 ((Value == -1) && ((Byte & 0x40) != 0))));
56 if (More || Padding != 0)
59 Count++;
60 if (More || Count < PadTo)
5761 Byte |= 0x80; // Mark this byte to show that more bytes will follow.
5862 *p++ = Byte;
5963 } while (More);
6064
6165 // Pad with 0x80 and emit a terminating byte at the end.
62 if (Padding != 0) {
66 if (Count < PadTo) {
6367 uint8_t PadValue = Value < 0 ? 0x7f : 0x00;
64 for (; Padding != 1; --Padding)
68 for (; Count < PadTo - 1; ++Count)
6569 *p++ = (PadValue | 0x80);
6670 *p++ = PadValue;
6771 }
7074
7175 /// Utility function to encode a ULEB128 value to an output stream.
7276 inline void encodeULEB128(uint64_t Value, raw_ostream &OS,
73 unsigned Padding = 0) {
77 unsigned PadTo = 0) {
78 unsigned Count = 0;
7479 do {
7580 uint8_t Byte = Value & 0x7f;
7681 Value >>= 7;
77 if (Value != 0 || Padding != 0)
82 Count++;
83 if (Value != 0 || Count < PadTo)
7884 Byte |= 0x80; // Mark this byte to show that more bytes will follow.
7985 OS << char(Byte);
8086 } while (Value != 0);
8187
8288 // Pad with 0x80 and emit a null byte at the end.
83 if (Padding != 0) {
84 for (; Padding != 1; --Padding)
89 if (Count < PadTo) {
90 for (; Count < PadTo - 1; ++Count)
8591 OS << '\x80';
8692 OS << '\x00';
93 Count++;
8794 }
8895 }
8996
9097 /// Utility function to encode a ULEB128 value to a buffer. Returns
9198 /// the length in bytes of the encoded value.
9299 inline unsigned encodeULEB128(uint64_t Value, uint8_t *p,
93 unsigned Padding = 0) {
100 unsigned PadTo = 0) {
94101 uint8_t *orig_p = p;
102 unsigned Count = 0;
95103 do {
96104 uint8_t Byte = Value & 0x7f;
97105 Value >>= 7;
98 if (Value != 0 || Padding != 0)
106 Count++;
107 if (Value != 0 || Count < PadTo)
99108 Byte |= 0x80; // Mark this byte to show that more bytes will follow.
100109 *p++ = Byte;
101110 } while (Value != 0);
102111
103112 // Pad with 0x80 and emit a null byte at the end.
104 if (Padding != 0) {
105 for (; Padding != 1; --Padding)
113 if (Count < PadTo) {
114 for (; Count < PadTo - 1; ++Count)
106115 *p++ = '\x80';
107116 *p++ = '\x00';
108117 }
118
109119 return (unsigned)(p - orig_p);
110120 }
111121
4747 }
4848
4949 /// EmitULEB128 - emit the specified unsigned leb128 value.
50 void AsmPrinter::EmitULEB128(uint64_t Value, const char *Desc,
51 unsigned PadTo) const {
50 void AsmPrinter::EmitPaddedULEB128(uint64_t Value, unsigned PadTo,
51 const char *Desc) const {
5252 if (isVerbose() && Desc)
5353 OutStreamer->AddComment(Desc);
5454
55 OutStreamer->EmitULEB128IntValue(Value, PadTo);
55 OutStreamer->EmitPaddedULEB128IntValue(Value, PadTo);
56 }
57
58 void AsmPrinter::EmitULEB128(uint64_t Value, const char *Desc) const {
59 if (isVerbose() && Desc)
60 OutStreamer->AddComment(Desc);
61
62 OutStreamer->EmitULEB128IntValue(Value);
5663 }
5764
5865 static const char *DecodeDWARFEncoding(unsigned Encoding) {
477477 sizeof(int8_t) + // TType format
478478 (HaveTTData ? TTypeBaseOffsetSize : 0) + // TType base offset size
479479 TTypeBaseOffset; // TType base offset
480 unsigned SizeAlign = (4 - TotalSize) & 3;
480 unsigned PadBytes = (4 - TotalSize) & 3;
481481
482482 if (HaveTTData) {
483483 // Account for any extra padding that will be added to the call site table
484484 // length.
485 Asm->EmitULEB128(TTypeBaseOffset, "@TType base offset", SizeAlign);
486 SizeAlign = 0;
485 Asm->EmitPaddedULEB128(TTypeBaseOffset, TTypeBaseOffsetSize + PadBytes,
486 "@TType base offset");
487 PadBytes = 0;
487488 }
488489
489490 bool VerboseAsm = Asm->OutStreamer->isVerboseAsm();
493494 Asm->EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site");
494495
495496 // Add extra padding if it wasn't added to the TType base offset.
496 Asm->EmitULEB128(CallSiteTableLength, "Call site table length", SizeAlign);
497 Asm->EmitPaddedULEB128(CallSiteTableLength,
498 CallSiteTableLengthSize + PadBytes,
499 "Call site table length");
497500
498501 // Emit the landing pad site information.
499502 unsigned idx = 0;
546549 Asm->EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site");
547550
548551 // Add extra padding if it wasn't added to the TType base offset.
549 Asm->EmitULEB128(CallSiteTableLength, "Call site table length", SizeAlign);
552 Asm->EmitPaddedULEB128(CallSiteTableLength,
553 CallSiteTableLengthSize + PadBytes,
554 "Call site table length");
550555
551556 unsigned Entry = 0;
552557 for (SmallVectorImpl::const_iterator
104104
105105 /// EmitULEB128Value - Special case of EmitULEB128Value that avoids the
106106 /// client having to pass in a MCExpr for constant integers.
107 void MCStreamer::EmitULEB128IntValue(uint64_t Value, unsigned Padding) {
107 void MCStreamer::EmitPaddedULEB128IntValue(uint64_t Value, unsigned PadTo) {
108108 SmallString<128> Tmp;
109109 raw_svector_ostream OSE(Tmp);
110 encodeULEB128(Value, OSE, Padding);
110 encodeULEB128(Value, OSE, PadTo);
111111 EmitBytes(OSE.str());
112 }
113
114 void MCStreamer::EmitULEB128IntValue(uint64_t Value) {
115 EmitPaddedULEB128IntValue(Value, 0);
112116 }
113117
114118 /// EmitSLEB128Value - Special case of EmitSLEB128Value that avoids the
296296
297297 WasmObjectWriter::~WasmObjectWriter() {}
298298
299 // Return the padding size to write a 32-bit value into a 5-byte ULEB128.
300 static unsigned PaddingFor5ByteULEB128(uint32_t X) {
301 return X == 0 ? 4 : (4u - (31u - countLeadingZeros(X)) / 7u);
302 }
303
304 // Return the padding size to write a 32-bit value into a 5-byte SLEB128.
305 static unsigned PaddingFor5ByteSLEB128(int32_t X) {
306 return 5 - getSLEB128Size(X);
307 }
308
309299 // Write out a section header and a patchable section size field.
310300 void WasmObjectWriter::startSection(SectionBookkeeping &Section,
311301 unsigned SectionId,
340330 report_fatal_error("section size does not fit in a uint32_t");
341331
342332 DEBUG(dbgs() << "endSection size=" << Size << "\n");
343 unsigned Padding = PaddingFor5ByteULEB128(Size);
344333
345334 // Write the final section size to the payload_len field, which follows
346335 // the section id byte.
347336 uint8_t Buffer[16];
348 unsigned SizeLen = encodeULEB128(Size, Buffer, Padding);
337 unsigned SizeLen = encodeULEB128(Size, Buffer, 5);
349338 assert(SizeLen == 5);
350339 getStream().pwrite((char *)Buffer, SizeLen, Section.SizeOffset);
351340 }
452441 static void
453442 WritePatchableLEB(raw_pwrite_stream &Stream, uint32_t X, uint64_t Offset) {
454443 uint8_t Buffer[5];
455 unsigned Padding = PaddingFor5ByteULEB128(X);
456 unsigned SizeLen = encodeULEB128(X, Buffer, Padding);
444 unsigned SizeLen = encodeULEB128(X, Buffer, 5);
457445 assert(SizeLen == 5);
458446 Stream.pwrite((char *)Buffer, SizeLen, Offset);
459447 }
463451 static void
464452 WritePatchableSLEB(raw_pwrite_stream &Stream, int32_t X, uint64_t Offset) {
465453 uint8_t Buffer[5];
466 unsigned Padding = PaddingFor5ByteSLEB128(X);
467 unsigned SizeLen = encodeSLEB128(X, Buffer, Padding);
454 unsigned SizeLen = encodeSLEB128(X, Buffer, 5);
468455 assert(SizeLen == 5);
469456 Stream.pwrite((char *)Buffer, SizeLen, Offset);
470457 }
115115 } else if (MO.isExpr()) {
116116 const MCOperandInfo &Info = Desc.OpInfo[i];
117117 llvm::MCFixupKind FixupKind;
118 size_t PaddedSize;
118 size_t PaddedSize = 5;
119119 if (Info.OperandType == WebAssembly::OPERAND_I32IMM) {
120120 FixupKind = MCFixupKind(WebAssembly::fixup_code_sleb128_i32);
121 PaddedSize = 5;
122121 } else if (Info.OperandType == WebAssembly::OPERAND_I64IMM) {
123122 FixupKind = MCFixupKind(WebAssembly::fixup_code_sleb128_i64);
124123 PaddedSize = 10;
126125 Info.OperandType == WebAssembly::OPERAND_OFFSET32 ||
127126 Info.OperandType == WebAssembly::OPERAND_TYPEINDEX) {
128127 FixupKind = MCFixupKind(WebAssembly::fixup_code_uleb128_i32);
129 PaddedSize = 5;
130128 } else if (Info.OperandType == WebAssembly::OPERAND_GLOBAL) {
131129 FixupKind = MCFixupKind(WebAssembly::fixup_code_global_index);
132 PaddedSize = 5;
133130 } else {
134131 llvm_unreachable("unexpected symbolic operand kind");
135132 }
137134 OS.tell() - Start, MO.getExpr(),
138135 FixupKind, MI.getLoc()));
139136 ++MCNumFixups;
140 encodeULEB128(0, OS, PaddedSize - 1);
137 encodeULEB128(0, OS, PaddedSize);
141138 } else {
142139 llvm_unreachable("unexpected operand kind");
143140 }
4545 EXPECT_SLEB128_EQ("\xc0\x00", 64, 0);
4646
4747 // Encode SLEB128 with some extra padding bytes
48 EXPECT_SLEB128_EQ("\x80\x00", 0, 1);
49 EXPECT_SLEB128_EQ("\x80\x80\x00", 0, 2);
50 EXPECT_SLEB128_EQ("\xff\x80\x00", 0x7f, 1);
51 EXPECT_SLEB128_EQ("\xff\x80\x80\x00", 0x7f, 2);
52 EXPECT_SLEB128_EQ("\x80\x81\x00", 0x80, 1);
53 EXPECT_SLEB128_EQ("\x80\x81\x80\x00", 0x80, 2);
54 EXPECT_SLEB128_EQ("\xc0\x7f", -0x40, 1);
55 EXPECT_SLEB128_EQ("\xc0\xff\x7f", -0x40, 2);
56 EXPECT_SLEB128_EQ("\x80\xff\x7f", -0x80, 1);
57 EXPECT_SLEB128_EQ("\x80\xff\xff\x7f", -0x80, 2);
48 EXPECT_SLEB128_EQ("\x80\x00", 0, 2);
49 EXPECT_SLEB128_EQ("\x80\x80\x00", 0, 3);
50 EXPECT_SLEB128_EQ("\xff\x80\x00", 0x7f, 3);
51 EXPECT_SLEB128_EQ("\xff\x80\x80\x00", 0x7f, 4);
52 EXPECT_SLEB128_EQ("\x80\x81\x00", 0x80, 3);
53 EXPECT_SLEB128_EQ("\x80\x81\x80\x00", 0x80, 4);
54 EXPECT_SLEB128_EQ("\xc0\x7f", -0x40, 2);
55
56 EXPECT_SLEB128_EQ("\xc0\xff\x7f", -0x40, 3);
57 EXPECT_SLEB128_EQ("\x80\xff\x7f", -0x80, 3);
58 EXPECT_SLEB128_EQ("\x80\xff\xff\x7f", -0x80, 4);
5859
5960 #undef EXPECT_SLEB128_EQ
6061 }
9293 EXPECT_ULEB128_EQ("\x81\x02", 0x101, 0);
9394
9495 // Encode ULEB128 with some extra padding bytes
95 EXPECT_ULEB128_EQ("\x80\x00", 0, 1);
96 EXPECT_ULEB128_EQ("\x80\x80\x00", 0, 2);
97 EXPECT_ULEB128_EQ("\xff\x00", 0x7f, 1);
98 EXPECT_ULEB128_EQ("\xff\x80\x00", 0x7f, 2);
99 EXPECT_ULEB128_EQ("\x80\x81\x00", 0x80, 1);
100 EXPECT_ULEB128_EQ("\x80\x81\x80\x00", 0x80, 2);
96 EXPECT_ULEB128_EQ("\x80\x00", 0, 2);
97 EXPECT_ULEB128_EQ("\x80\x80\x00", 0, 3);
98 EXPECT_ULEB128_EQ("\xff\x00", 0x7f, 2);
99 EXPECT_ULEB128_EQ("\xff\x80\x00", 0x7f, 3);
100 EXPECT_ULEB128_EQ("\x80\x81\x00", 0x80, 3);
101 EXPECT_ULEB128_EQ("\x80\x81\x80\x00", 0x80, 4);
101102
102103 #undef EXPECT_ULEB128_EQ
103104 }