Skip to content
Snippets Groups Projects
Commit 7365ea6a authored by Mehdi Amini's avatar Mehdi Amini
Browse files

Fix os_log formating with arbitrary precision and field width

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@289761 91177308-0d34-0410-b5e6-96231b3b80d8
parent 5d99c394
No related branches found
No related tags found
No related merge requests found
......@@ -22,6 +22,9 @@ private:
const Expr *E = nullptr;
Optional<OSLogBufferItem::Kind> Kind;
Optional<unsigned> Size;
Optional<const Expr *> Count;
Optional<const Expr *> Precision;
Optional<const Expr *> FieldWidth;
unsigned char Flags = 0;
};
SmallVector<ArgData, 4> ArgsData;
......@@ -84,7 +87,7 @@ public:
ArgsData.back().Size = precision.getConstantAmount();
break;
case clang::analyze_format_string::OptionalAmount::Arg: // "%.*s"
ArgsData.back().Kind = OSLogBufferItem::CountKind;
ArgsData.back().Count = Args[precision.getArgIndex()];
break;
case clang::analyze_format_string::OptionalAmount::Invalid:
return false;
......@@ -100,7 +103,7 @@ public:
ArgsData.back().Size = precision.getConstantAmount();
break;
case clang::analyze_format_string::OptionalAmount::Arg: // "%.*P"
ArgsData.back().Kind = OSLogBufferItem::CountKind;
ArgsData.back().Count = Args[precision.getArgIndex()];
break;
case clang::analyze_format_string::OptionalAmount::Invalid:
return false;
......@@ -108,8 +111,14 @@ public:
break;
}
default:
if (FS.getPrecision().hasDataArgument()) {
ArgsData.back().Precision = Args[FS.getPrecision().getArgIndex()];
}
break;
}
if (FS.getFieldWidth().hasDataArgument()) {
ArgsData.back().FieldWidth = Args[FS.getFieldWidth().getArgIndex()];
}
if (FS.isPrivate()) {
ArgsData.back().Flags |= OSLogBufferItem::IsPrivate;
......@@ -123,6 +132,22 @@ public:
void computeLayout(ASTContext &Ctx, OSLogBufferLayout &Layout) const {
Layout.Items.clear();
for (auto &Data : ArgsData) {
if (Data.FieldWidth) {
CharUnits Size = Ctx.getTypeSizeInChars((*Data.FieldWidth)->getType());
Layout.Items.emplace_back(OSLogBufferItem::ScalarKind, *Data.FieldWidth,
Size, 0);
}
if (Data.Precision) {
CharUnits Size = Ctx.getTypeSizeInChars((*Data.Precision)->getType());
Layout.Items.emplace_back(OSLogBufferItem::ScalarKind, *Data.Precision,
Size, 0);
}
if (Data.Count) {
// "%.*P" has an extra "count" that we insert before the argument.
CharUnits Size = Ctx.getTypeSizeInChars((*Data.Count)->getType());
Layout.Items.emplace_back(OSLogBufferItem::CountKind, *Data.Count, Size,
0);
}
if (Data.Size)
Layout.Items.emplace_back(Ctx, CharUnits::fromQuantity(*Data.Size),
Data.Flags);
......
......@@ -489,6 +489,55 @@ void test_builtin_os_log_wide(void *buf, const char *data, wchar_t *str) {
__builtin_os_log_format(buf, "%S", str);
}
// CHECK-LABEL: define void @test_builtin_os_log_precision_width
// CHECK: (i8* [[BUF:%.*]], i8* [[DATA:%.*]], i32 [[PRECISION:%.*]], i32 [[WIDTH:%.*]])
void test_builtin_os_log_precision_width(void *buf, const char *data,
int precision, int width) {
volatile int len;
// CHECK: store i8* [[BUF]], i8** [[BUF_ADDR:%.*]], align 8
// CHECK: store i8* [[DATA]], i8** [[DATA_ADDR:%.*]], align 8
// CHECK: store i32 [[PRECISION]], i32* [[PRECISION_ADDR:%.*]], align 4
// CHECK: store i32 [[WIDTH]], i32* [[WIDTH_ADDR:%.*]], align 4
// CHECK: store volatile i32 24,
len = __builtin_os_log_format_buffer_size("Hello %*.*s World", precision, width, data);
// CHECK: [[BUF2:%.*]] = load i8*, i8** [[BUF_ADDR]]
// CHECK: [[SUMMARY:%.*]] = getelementptr i8, i8* [[BUF2]], i64 0
// CHECK: store i8 2, i8* [[SUMMARY]]
// CHECK: [[NUM_ARGS:%.*]] = getelementptr i8, i8* [[BUF2]], i64 1
// CHECK: store i8 3, i8* [[NUM_ARGS]]
// CHECK: [[ARG1_DESC:%.*]] = getelementptr i8, i8* [[BUF2]], i64 2
// CHECK: store i8 0, i8* [[ARG1_DESC]]
// CHECK: [[ARG1_SIZE:%.*]] = getelementptr i8, i8* [[BUF2]], i64 3
// CHECK: store i8 4, i8* [[ARG1_SIZE]]
// CHECK: [[ARG1:%.*]] = getelementptr i8, i8* [[BUF2]], i64 4
// CHECK: [[ARG1_INT:%.*]] = bitcast i8* [[ARG1]] to i32*
// CHECK: [[ARG1_VAL:%.*]] = load i32, i32* [[PRECISION_ADDR]]
// CHECK: store i32 [[ARG1_VAL]], i32* [[ARG1_INT]]
// CHECK: [[ARG2_DESC:%.*]] = getelementptr i8, i8* [[BUF2]], i64 8
// CHECK: store i8 16, i8* [[ARG2_DESC]]
// CHECK: [[ARG2_SIZE:%.*]] = getelementptr i8, i8* [[BUF2]], i64 9
// CHECK: store i8 4, i8* [[ARG2_SIZE]]
// CHECK: [[ARG2:%.*]] = getelementptr i8, i8* [[BUF2]], i64 10
// CHECK: [[ARG2_INT:%.*]] = bitcast i8* [[ARG2]] to i32*
// CHECK: [[ARG2_VAL:%.*]] = load i32, i32* [[WIDTH_ADDR]]
// CHECK: store i32 [[ARG2_VAL]], i32* [[ARG2_INT]]
// CHECK: [[ARG3_DESC:%.*]] = getelementptr i8, i8* [[BUF2]], i64 14
// CHECK: store i8 32, i8* [[ARG3_DESC]]
// CHECK: [[ARG3_SIZE:%.*]] = getelementptr i8, i8* [[BUF2]], i64 15
// CHECK: store i8 8, i8* [[ARG3_SIZE]]
// CHECK: [[ARG3:%.*]] = getelementptr i8, i8* [[BUF2]], i64 16
// CHECK: [[ARG3_PTR:%.*]] = bitcast i8* [[ARG3]] to i8**
// CHECK: [[DATA2:%.*]] = load i8*, i8** [[DATA_ADDR]]
// CHECK: store i8* [[DATA2]], i8** [[ARG3_PTR]]
__builtin_os_log_format(buf, "Hello %*.*s World", precision, width, data);
}
// CHECK-LABEL: define void @test_builtin_os_log_percent
// CHECK: (i8* [[BUF:%.*]], i8* [[DATA1:%.*]], i8* [[DATA2:%.*]])
// Check that the %% which does not consume any argument is correctly handled
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment