Skip to content

Commit 036ca20

Browse files
cmt0facebook-github-bot
authored andcommitted
Add ETPRIsize_t support to ExecuTorch for Xtensa (pytorch#7895)
Summary: topic: not user facing Our Xtensa G3's toolchain, which is as recent as RJ-2024.3 release doesn't have %zu format specifier support. Since we only have the precompiled libc.a provided from cadence -- it seems from the disassembly that only the following are supported %c: character %s: string %d: decimal integer %i: decimal integer (same as %d) %u: unsigned decimal integer %x: hexadecimal integer %X: uppercase hexadecimal integer %p: pointer which is consistent with what I've seen come-out from ET_LOG prints that pass through the vsnprintf specifier Haven't heard of a 64-bit Xtensa DSP, so I think this 'lu' specifier mapping should work for all Xtensa toolchains regardless of vsnprintf implementation. This diff also updates a couple of places where I most commonly see the mishandled %zu specifier. If the changes are okay, I can more widely update print statements in ExecuTorch. It would touch a lot of files, some of which would never be compiled for Xtensa. Differential Revision: D68131252
1 parent 0dc192b commit 036ca20

File tree

3 files changed

+49
-40
lines changed

3 files changed

+49
-40
lines changed

runtime/core/hierarchical_allocator.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,15 @@ class HierarchicalAllocator final {
6262
ET_CHECK_OR_RETURN_ERROR(
6363
memory_id < buffers_.size(),
6464
InvalidArgument,
65-
"id %" PRIu32 " >= %zu",
65+
"id %" PRIu32 " >= %" ET_PRIsize_t,
6666
memory_id,
6767
buffers_.size());
6868
Span<uint8_t> buffer = buffers_[memory_id];
6969
ET_CHECK_OR_RETURN_ERROR(
7070
offset_bytes + size_bytes <= buffer.size(),
7171
MemoryAllocationFailed,
72-
"offset_bytes (%zu) + size_bytes (%zu) >= allocator size (%zu) "
72+
"offset_bytes (%" ET_PRIsize_t ") + size_bytes (%" ET_PRIsize_t
73+
") >= allocator size (%" ET_PRIsize_t
7374
"for memory_id %" PRIu32,
7475
offset_bytes,
7576
size_bytes,

runtime/executor/method.cpp

Lines changed: 39 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <executorch/runtime/kernel/kernel_runtime_context.h>
2525
#include <executorch/runtime/kernel/operator_registry.h>
2626
#include <executorch/runtime/platform/assert.h>
27+
#include <executorch/runtime/platform/compiler.h>
2728
#include <executorch/runtime/platform/log.h>
2829
#include <executorch/runtime/platform/profiler.h>
2930
#include <executorch/schema/program_generated.h>
@@ -238,7 +239,7 @@ Result<InstructionArgs> gen_instruction_arguments(
238239
ET_CHECK_OR_RETURN_ERROR(
239240
arg_idx < num_values,
240241
InvalidProgram,
241-
"Arg index %d >= %zu",
242+
"Arg index %d >= %" ET_PRIsize_t,
242243
arg_idx,
243244
num_values);
244245
arg_list[i] = &values[arg_idx];
@@ -311,7 +312,7 @@ Error Method::parse_values() {
311312
executorch_flatbuffer::KernelTypes::Null ||
312313
serialization_value->val() != nullptr),
313314
InvalidProgram,
314-
"Null value at index %zu",
315+
"Null value at index %" ET_PRIsize_t,
315316
i);
316317

317318
const auto val = serialization_value->val();
@@ -340,7 +341,7 @@ Error Method::parse_values() {
340341
const auto items =
341342
static_cast<const executorch_flatbuffer::IntList*>(val)->items();
342343
ET_CHECK_OR_RETURN_ERROR(
343-
items != nullptr, InvalidProgram, "Missing list at index %zu", i);
344+
items != nullptr, InvalidProgram, "Missing list at index %" ET_PRIsize_t, i);
344345
// Allocate space for boxed and unboxed list representations using
345346
// values_ as source of truth
346347
auto* evalp_list =
@@ -356,7 +357,7 @@ Error Method::parse_values() {
356357
ET_CHECK_OR_RETURN_ERROR(
357358
value_index >= 0 && value_index < n_value,
358359
InvalidProgram,
359-
"Invalid value index %" PRId64 " for IntList %zu index %zu",
360+
"Invalid value index %" PRId64 " for IntList %" ET_PRIsize_t " index %" ET_PRIsize_t,
360361
value_index,
361362
i,
362363
j);
@@ -369,7 +370,7 @@ Error Method::parse_values() {
369370
const auto items =
370371
static_cast<const executorch_flatbuffer::BoolList*>(val)->items();
371372
ET_CHECK_OR_RETURN_ERROR(
372-
items != nullptr, InvalidProgram, "Missing list at index %zu", i);
373+
items != nullptr, InvalidProgram, "Missing list at index %" ET_PRIsize_t, i);
373374
// NOTE: This is technically not portable. A platform could technically
374375
// define boolean as something longer than a byte. This would be an
375376
// exceptionally rare case, and this type is currently unused in any
@@ -384,7 +385,7 @@ Error Method::parse_values() {
384385
const auto items =
385386
static_cast<const executorch_flatbuffer::DoubleList*>(val)->items();
386387
ET_CHECK_OR_RETURN_ERROR(
387-
items != nullptr, InvalidProgram, "Missing list at index %zu", i);
388+
items != nullptr, InvalidProgram, "Missing list at index %" ET_PRIsize_t, i);
388389
new (&values_[i])
389390
EValue(exec_aten::ArrayRef<double>(items->data(), items->size()));
390391
} break;
@@ -395,7 +396,7 @@ Error Method::parse_values() {
395396
ET_CHECK_OR_RETURN_ERROR(
396397
fb_str != nullptr,
397398
InvalidProgram,
398-
"Missing string at index %zu",
399+
"Missing string at index %" ET_PRIsize_t,
399400
i);
400401
new (&values_[i]) EValue(fb_str->c_str(), fb_str->size());
401402
} break;
@@ -407,7 +408,7 @@ Error Method::parse_values() {
407408
if (!t.ok()) {
408409
ET_LOG(
409410
Error,
410-
"Failed parsing tensor at index %zu: 0x%" PRIx32,
411+
"Failed parsing tensor at index %" ET_PRIsize_t ": 0x%" PRIx32,
411412
i,
412413
static_cast<uint32_t>(t.error()));
413414
return t.error();
@@ -429,7 +430,7 @@ Error Method::parse_values() {
429430
if (!tensors.ok()) {
430431
ET_LOG(
431432
Error,
432-
"Failed parsing tensor list at index %zu: 0x%" PRIx32,
433+
"Failed parsing tensor list at index %" ET_PRIsize_t ": 0x%" PRIx32,
433434
i,
434435
static_cast<uint32_t>(tensors.error()));
435436
return tensors.error();
@@ -452,7 +453,7 @@ Error Method::parse_values() {
452453
if (!tensors.ok()) {
453454
ET_LOG(
454455
Error,
455-
"Failed parsing optional tensor list at index %zu: 0x%" PRIx32,
456+
"Failed parsing optional tensor list at index %" ET_PRIsize_t ": 0x%" PRIx32,
456457
i,
457458
static_cast<uint32_t>(tensors.error()));
458459
return tensors.error();
@@ -467,7 +468,7 @@ Error Method::parse_values() {
467468
// schema.fbs
468469
ET_LOG(
469470
Error,
470-
"Unknown KernelTypes value %" PRIu32 " at index %zu",
471+
"Unknown KernelTypes value %" PRIu32 " at index %" ET_PRIsize_t,
471472
static_cast<uint32_t>(serialization_value->val_type()) - 1,
472473
i);
473474
return Error::InvalidProgram;
@@ -509,7 +510,7 @@ Error populate_operator_name(
509510
cx < operator_name_size,
510511
Internal,
511512
"Operator name %s%s%s with length %d "
512-
"truncated to %zu due to internal buffer limit.",
513+
"truncated to %" ET_PRIsize_t " due to internal buffer limit.",
513514
op->name()->c_str(),
514515
has_overload ? "." : "",
515516
has_overload ? op->overload()->c_str() : "",
@@ -569,7 +570,7 @@ Error Method::resolve_operator(
569570
ET_CHECK_OR_RETURN_ERROR(
570571
err == Error::Ok,
571572
InvalidArgument,
572-
"Error setting dim_order %zu: 0x%" PRIx32,
573+
"Error setting dim_order %" ET_PRIsize_t ": 0x%" PRIx32,
573574
i,
574575
static_cast<uint32_t>(err));
575576
meta[count].dim_order_ =
@@ -694,7 +695,7 @@ Error Method::init(executorch_flatbuffer::ExecutionPlan* s_plan) {
694695
ET_CHECK_OR_RETURN_ERROR(
695696
s_instructions != nullptr,
696697
InvalidProgram,
697-
"Missing instructions in chain %zu",
698+
"Missing instructions in chain %" ET_PRIsize_t,
698699
i);
699700
auto num_instructions = s_instructions->size();
700701
auto chain_instruction_kernels =
@@ -717,7 +718,7 @@ Error Method::init(executorch_flatbuffer::ExecutionPlan* s_plan) {
717718
ET_CHECK_OR_RETURN_ERROR(
718719
instruction != nullptr && instruction->instr_args() != nullptr,
719720
InvalidProgram,
720-
"Null instruction at index %zu",
721+
"Null instruction at index %" ET_PRIsize_t,
721722
instr_idx);
722723

723724
const void* instr_args = instruction->instr_args();
@@ -783,7 +784,7 @@ Error Method::init(executorch_flatbuffer::ExecutionPlan* s_plan) {
783784
ET_CHECK_OR_RETURN_ERROR(
784785
index >= 0 && index < n_value_,
785786
InvalidProgram,
786-
"Index %d negative or >= %zu",
787+
"Index %d negative or >= %" ET_PRIsize_t,
787788
index,
788789
n_value_);
789790
chain_instruction_arg_lists[instr_idx] = InstructionArgs();
@@ -831,7 +832,7 @@ Method::set_input(const EValue& input_evalue, size_t input_idx) {
831832
ET_CHECK_OR_RETURN_ERROR(
832833
input_idx < inputs_size(),
833834
InvalidArgument,
834-
"Input index (%zu) must be less than the number of inputs in method (%zu).",
835+
"Input index (%" ET_PRIsize_t ") must be less than the number of inputs in method (%" ET_PRIsize_t ").",
835836
input_idx,
836837
inputs_size());
837838

@@ -843,7 +844,7 @@ Method::set_input(const EValue& input_evalue, size_t input_idx) {
843844
tag_to_string(e.tag, tag_name.data(), tag_name.size());
844845
ET_LOG(
845846
Error,
846-
"Input %zu was expected to be a Tensor or primitive but was %s.",
847+
"Input %" ET_PRIsize_t " was expected to be a Tensor or primitive but was %s.",
847848
input_idx,
848849
tag_name.data());
849850
#endif
@@ -876,7 +877,7 @@ Method::set_input(const EValue& input_evalue, size_t input_idx) {
876877
ET_CHECK_OR_RETURN_ERROR(
877878
t_dst.scalar_type() == t_src.scalar_type(),
878879
InvalidArgument,
879-
"Input %zu has unexpected scalar type: expected %s but was %s.",
880+
"Input %" ET_PRIsize_t " has unexpected scalar type: expected %s but was %s.",
880881
input_idx,
881882
executorch::runtime::toString(t_dst.scalar_type()),
882883
executorch::runtime::toString(t_src.scalar_type()));
@@ -886,7 +887,7 @@ Method::set_input(const EValue& input_evalue, size_t input_idx) {
886887
ET_CHECK_OR_RETURN_ERROR(
887888
err == Error::Ok,
888889
InvalidArgument,
889-
"Error setting input %zu: 0x%" PRIx32,
890+
"Error setting input %" ET_PRIsize_t ": 0x%" PRIx32,
890891
input_idx,
891892
static_cast<uint32_t>(err));
892893
Error error;
@@ -899,15 +900,15 @@ Method::set_input(const EValue& input_evalue, size_t input_idx) {
899900
ET_CHECK_OR_RETURN_ERROR(
900901
error == Error::Ok,
901902
InvalidArgument,
902-
"Error setting data_ptr %zu: 0x%" PRIx32,
903+
"Error setting data_ptr %" ET_PRIsize_t ": 0x%" PRIx32,
903904
input_idx,
904905
static_cast<uint32_t>(error));
905906
// Prims have to be the same as what was traced
906907
} else if (e.isInt()) {
907908
ET_CHECK_OR_RETURN_ERROR(
908909
e.toInt() == input_evalue.toInt(),
909910
InvalidArgument,
910-
"The %zu-th input of method should have the same value as the input_evalue, but got %" PRId64
911+
"The %" ET_PRIsize_t "-th input of method should have the same value as the input_evalue, but got %" PRId64
911912
" and %" PRId64,
912913
input_idx,
913914
e.toInt(),
@@ -916,7 +917,7 @@ Method::set_input(const EValue& input_evalue, size_t input_idx) {
916917
ET_CHECK_OR_RETURN_ERROR(
917918
e.toBool() == input_evalue.toBool(),
918919
InvalidArgument,
919-
"The %zu-th input of method should have the same value as the input_evalue, but got %" PRId64
920+
"The %" ET_PRIsize_t "-th input of method should have the same value as the input_evalue, but got %" PRId64
920921
" and %" PRId64,
921922
input_idx,
922923
(int64_t)e.toBool(),
@@ -944,15 +945,15 @@ Method::set_input(const EValue& input_evalue, size_t input_idx) {
944945
ET_CHECK_OR_RETURN_ERROR(
945946
is_equal,
946947
InvalidArgument,
947-
"The %zu-th input of method should have the same value as the input_evalue, but get %f and %f",
948+
"The %" ET_PRIsize_t "-th input of method should have the same value as the input_evalue, but get %f and %f",
948949
input_idx,
949950
lhs,
950951
rhs);
951952
} else if (e.isString()) {
952953
ET_CHECK_OR_RETURN_ERROR(
953954
e.toString() == input_evalue.toString(),
954955
InvalidArgument,
955-
"The %zu-th input of method should have the same value as the input_evalue, but get %s and %s",
956+
"The %" ET_PRIsize_t "-th input of method should have the same value as the input_evalue, but get %s and %s",
956957
input_idx,
957958
e.toString().data(),
958959
input_evalue.toString().data());
@@ -984,7 +985,7 @@ Method::set_inputs(const exec_aten::ArrayRef<EValue>& input_evalues) {
984985
ET_CHECK_OR_RETURN_ERROR(
985986
input_size == input_evalues.size(),
986987
InvalidArgument,
987-
"The length of given input array (%zu) must be same as the number of inputs in method (%zu).",
988+
"The length of given input array (%" ET_PRIsize_t ") must be same as the number of inputs in method (%" ET_PRIsize_t ").",
988989
input_evalues.size(),
989990
input_size);
990991

@@ -1009,7 +1010,7 @@ Method::set_output_data_ptr(void* buffer, size_t size, size_t output_idx) {
10091010
ET_CHECK_OR_RETURN_ERROR(
10101011
output_idx < outputs_size(),
10111012
InvalidArgument,
1012-
"output_idx: %zu > num_outputs: %zu",
1013+
"output_idx: %" ET_PRIsize_t " > num_outputs: %" ET_PRIsize_t,
10131014
output_idx,
10141015
outputs_size());
10151016

@@ -1028,7 +1029,7 @@ Method::set_output_data_ptr(void* buffer, size_t size, size_t output_idx) {
10281029
if (tensor_meta->is_memory_planned()) {
10291030
ET_LOG(
10301031
Error,
1031-
"Output %zu is memory planned, or is a constant. Cannot override "
1032+
"Output %" ET_PRIsize_t " is memory planned, or is a constant. Cannot override "
10321033
"the existing data pointer.",
10331034
output_idx);
10341035
return Error::InvalidState;
@@ -1048,7 +1049,7 @@ Method::set_output_data_ptr(void* buffer, size_t size, size_t output_idx) {
10481049
ET_CHECK_OR_RETURN_ERROR(
10491050
t.nbytes() <= size,
10501051
InvalidArgument,
1051-
"buffer size: %zu is smaller then expected tensor size: %zu",
1052+
"buffer size: %" ET_PRIsize_t " is smaller then expected tensor size: %" ET_PRIsize_t,
10521053
size,
10531054
t.nbytes());
10541055

@@ -1107,7 +1108,7 @@ Error Method::execute_instruction() {
11071108
ET_CHECK_OR_RETURN_ERROR(
11081109
step_state_.instr_idx < instructions->size(),
11091110
Internal,
1110-
"Instr index %zu >= chain[%zu] instr count %zu",
1111+
"Instr index %" ET_PRIsize_t " >= chain[%" ET_PRIsize_t "] instr count %" ET_PRIsize_t,
11111112
step_state_.instr_idx,
11121113
step_state_.chain_idx,
11131114
(size_t)instructions->size());
@@ -1134,7 +1135,7 @@ Error Method::execute_instruction() {
11341135
ET_UNUSED auto op = serialization_plan_->operators()->Get(op_index);
11351136
ET_LOG(
11361137
Error,
1137-
"KernelCall failed at instruction %zu:%zu in operator %s.%s: 0x%x",
1138+
"KernelCall failed at instruction %" ET_PRIsize_t ":%" ET_PRIsize_t " in operator %s.%s: 0x%x",
11381139
step_state_.chain_idx,
11391140
step_state_.instr_idx,
11401141
op->name()->c_str(),
@@ -1164,7 +1165,7 @@ Error Method::execute_instruction() {
11641165
delegate_idx < n_delegate_,
11651166
Internal,
11661167
"DELEGATE_CALL index %" PRIu32
1167-
" >= num delegates %zu at instruction %zu",
1168+
" >= num delegates %" ET_PRIsize_t " at instruction %" ET_PRIsize_t,
11681169
delegate_idx,
11691170
n_delegate_,
11701171
step_state_.instr_idx);
@@ -1178,7 +1179,7 @@ Error Method::execute_instruction() {
11781179
if (err != Error::Ok) {
11791180
ET_LOG(
11801181
Error,
1181-
"CALL_DELEGATE execute failed at instruction %zu: 0x%" PRIx32,
1182+
"CALL_DELEGATE execute failed at instruction %" ET_PRIsize_t ": 0x%" PRIx32,
11821183
step_state_.instr_idx,
11831184
static_cast<uint32_t>(err));
11841185
}
@@ -1351,7 +1352,7 @@ Error Method::execute() {
13511352
ET_CHECK_OR_RETURN_ERROR(
13521353
instructions != nullptr,
13531354
Internal,
1354-
"chain %zu has no instructions field",
1355+
"chain %" ET_PRIsize_t " has no instructions field",
13551356
step_state_.chain_idx);
13561357

13571358
// Loop over instructions
@@ -1391,12 +1392,12 @@ MethodMeta Method::method_meta() const {
13911392
}
13921393

13931394
const EValue& Method::get_value(size_t i) const {
1394-
ET_CHECK_MSG(i < n_value_, "%zu >= %zu", i, n_value_);
1395+
ET_CHECK_MSG(i < n_value_, "%" ET_PRIsize_t " >= %" ET_PRIsize_t, i, n_value_);
13951396
return values_[i];
13961397
}
13971398

13981399
EValue& Method::mutable_value(size_t i) {
1399-
ET_CHECK_MSG(i < n_value_, "%zu >= %zu", i, n_value_);
1400+
ET_CHECK_MSG(i < n_value_, "%" ET_PRIsize_t " >= %" ET_PRIsize_t, i, n_value_);
14001401
return values_[i];
14011402
}
14021403

@@ -1406,7 +1407,7 @@ size_t Method::inputs_size() const {
14061407
}
14071408

14081409
size_t Method::get_input_index(size_t i) const {
1409-
ET_CHECK_MSG(i < inputs_size(), "%zu >= %zu", i, inputs_size());
1410+
ET_CHECK_MSG(i < inputs_size(), "%" ET_PRIsize_t " >= %" ET_PRIsize_t, i, inputs_size());
14101411
return static_cast<size_t>(serialization_plan_->inputs()->Get(i));
14111412
}
14121413

@@ -1424,7 +1425,7 @@ size_t Method::outputs_size() const {
14241425
}
14251426

14261427
size_t Method::get_output_index(size_t i) const {
1427-
ET_CHECK_MSG(i < outputs_size(), "%zu >= %zu", i, outputs_size());
1428+
ET_CHECK_MSG(i < outputs_size(), "%" ET_PRIsize_t " >= %" ET_PRIsize_t, i, outputs_size());
14281429
return static_cast<size_t>(serialization_plan_->outputs()->Get(i));
14291430
}
14301431

runtime/platform/compiler.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,13 @@
146146
#define ET_FUNCTION __FUNCTION__
147147
#endif // __has_builtin(__builtin_FUNCTION)
148148

149+
// As of G3 RJ-2024.3 toolchain, zu format specifier is not supported for Xtensa
150+
#if defined(__XTENSA__)
151+
#define ET_PRIsize_t "lu"
152+
#else
153+
#define ET_PRIsize_t "zu"
154+
#endif
155+
149156
// Whether the compiler supports GNU statement expressions.
150157
// https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html
151158
#ifndef ET_HAVE_GNU_STATEMENT_EXPRESSIONS

0 commit comments

Comments
 (0)