This is an archive of the discontinued LLVM Phabricator instance.

Add support of Windows Trace Logging macros
ClosedPublic

Authored by RIscRIpt on Aug 23 2023, 3:22 AM.

Details

Summary

Consider the following code:

#include <windows.h>
#include <TraceLoggingActivity.h>
#include <TraceLoggingProvider.h>
#include <winmeta.h>

TRACELOGGING_DEFINE_PROVIDER(
    g_hMyComponentProvider,
    "SimpleTraceLoggingProvider",
    // {0205c616-cf97-5c11-9756-56a2cee02ca7}
    (0x0205c616,0xcf97,0x5c11,0x97,0x56,0x56,0xa2,0xce,0xe0,0x2c,0xa7));

void test()
{
    TraceLoggingFunction(g_hMyComponentProvider);
}

int main()
{
    TraceLoggingRegister(g_hMyComponentProvider);
    test();
    TraceLoggingUnregister(g_hMyComponentProvider);
}

It compiles with MSVC, but clang-cl reports an error:

C:\Program Files (x86)\Windows Kits\10\\include\10.0.22621.0\\shared/TraceLoggingActivity.h(377,30): note: expanded from macro '_tlgThisFunctionName'
#define _tlgThisFunctionName __FUNCTION__
                             ^
.\tl.cpp(14,5): error: cannot initialize an array element of type 'char' with an lvalue of type 'const char[5]'
    TraceLoggingFunction(g_hMyComponentProvider);
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The second commit is not needed to support above code, however, during isolated tests in ms_predefined_expr.cpp
I found that MSVC accepts code with constexpr, whereas clang-cl does not.
I see that in most places PredefinedExpr is supported in constant evaluation, so I didn't wrap my code with `if(MicrosoftExt)`.

Diff Detail

Event Timeline

RIscRIpt created this revision.Aug 23 2023, 3:22 AM
Herald added a project: Restricted Project. · View Herald TranscriptAug 23 2023, 3:22 AM
Herald added a subscriber: pengfei. · View Herald Transcript
RIscRIpt requested review of this revision.Aug 23 2023, 3:22 AM
Herald added a project: Restricted Project. · View Herald TranscriptAug 23 2023, 3:22 AM
Herald added a subscriber: cfe-commits. · View Herald Transcript
cor3ntin added inline comments.Aug 23 2023, 4:46 AM
clang/lib/Sema/Sema.cpp
1495–1499

I think this is reimplementing getCurFunctionOrMethodDecl
maybe we want to do

if(Decl* DC = getCurFunctionOrMethodDecl())
    return DC;
return dyn_cast_or_null<Decl>(CurrentContext);

Or something like that

RIscRIpt marked an inline comment as done.Aug 23 2023, 5:11 AM
RIscRIpt added inline comments.
clang/lib/Sema/Sema.cpp
1495–1499

Well, unfortunately, not really.

The previous implementation did call getCurFunctionOrMethodDecl(), but it returned nullptr when we were inside a RecordDecl.
If you examine the implementation of getFunctionLevelDeclContext(bool AllowLambda), it halts if isa<RecordDecl>(DC). I tried patching getFunctionLevelDeclContext() to skip RecordDecl, but this triggered around 70 clang/tests. I didn't want to delve into understanding the failure of each test. If you believe there's an issue with our current code, I can allocate time to investigate each specific test case.

cor3ntin added inline comments.Aug 23 2023, 6:05 AM
clang/lib/Sema/Sema.cpp
1495–1499

You are right, i missed that.
I wish we had a better name for this function but I can't think of anything

1496–1497
RIscRIpt marked 2 inline comments as done.Aug 23 2023, 6:32 AM
RIscRIpt added inline comments.
clang/lib/Sema/Sema.cpp
1495–1499

A perfect name would be getFunctionLevelDeclContext, but it's taken. Welp... I'll try to dig-into related functions, and update when I find something. An alternative solution would be to parameterize (in some way) getFunctionLevelDeclContext (e.g. add bool flags, or list of skippable types, etc.).

RIscRIpt updated this revision to Diff 553122.Aug 24 2023, 7:21 AM
RIscRIpt marked an inline comment as done.

Rebase onto main, address review comments

clang/lib/Sema/Sema.cpp
1495–1499

A perfect name would be getFunctionLevelDeclContext, but it's taken.

No, it's not. I found a better one, which was hiding in a plain sight.

Regarding using a common implementation: with a new function name it's clear that we cannot do that - they serve different purposes. For example, this function may return BlockDecl or CapturedDecl (which is accepted by PredefinedExpr::ComputeName) whereas getFunctionLevelDeclContext cannot.

RIscRIpt updated this revision to Diff 553123.Aug 24 2023, 7:28 AM
RIscRIpt marked an inline comment as done.

Use isa<...> in getPredefinedExprDeclContext

I missed this comment

The current implementation of getPredefinedExprDeclContext could be easily moved to a static function inside clang/lib/Sema/SemaExpr.cpp as it depends only on Sema::CurContext WDYT?

Looks mostly good to me, thanks!

The current implementation of getPredefinedExprDeclContext could be easily moved to a static function inside clang/lib/Sema/SemaExpr.cpp as it depends only on Sema::CurContext WDYT?

With the new name, that would make sense. we could keep close to where it is used.

clang/include/clang/Sema/Sema.h
3617–3620 ↗(On Diff #553123)
clang/lib/AST/ExprConstant.cpp
7527–7529

I wonder if we should modify the new interpreter at the same time to avoid giving more work to @tbaeder.
You can model it on ByteCodeExprGen<Emitter>::VisitSubstNonTypeTemplateParmExpr

clang/lib/Sema/Sema.cpp
1495–1499

Yeah, until we find another use case for this thing, this looks reasonable.

I also thought of getAnyFunctionContext or something along those lines but.. meh. what you have is fine, thanks!

RIscRIpt updated this revision to Diff 553437.Aug 25 2023, 4:26 AM
RIscRIpt marked 2 inline comments as done.

Address review comments

Regarding new interpreter.

It takes more time and effort than I expected.
Here's what I found:

  1. Assertion in ByteCodeExprGen<Emitter>::VisitPredefinedExpr seems unnecessary.
  2. StringLiteral of PredefinedExpr gets initialized in ByteCodeExprGen<Emitter>::VisitStringLiteral; I observe creation of InitMap, and initialization of each element of array.
  3. However when I am at the following call-stack (just before exiting constexpr interpreter and doing final checks):
00 00000066`04580990 00007ff6`55fb7257     clang!clang::interp::CheckArrayInitialized+0x257 [C:\projects\my-llvm\clang\lib\AST\Interp\Interp.cpp @ 425] 
01 00000066`04580b50 00007ff6`55f67ae6     clang!clang::interp::CheckCtorCall+0xc7 [C:\projects\my-llvm\clang\lib\AST\Interp\Interp.cpp @ 476] 
02 00000066`04580bb0 00007ff6`55ebdd17     clang!clang::interp::CheckGlobalCtor+0x36 [C:\projects\my-llvm\clang\lib\AST\Interp\Interp.h @ 1681] 
03 00000066`04580bf0 00007ff6`55fb3e3d     clang!clang::interp::EvalEmitter::emitCheckGlobalCtor+0x57 [C:\projects\my-llvm\build\tools\clang\lib\AST\Opcodes.inc @ 4133] 
04 00000066`04580c20 00007ff6`55fb4db1     clang!clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::visitGlobalInitializer+0xdd [C:\projects\my-llvm\clang\lib\AST\Interp\ByteCodeExprGen.h @ 180] 
05 00000066`04580c90 00007ff6`55fb33ce     clang!clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::visitVarDecl+0x291 [C:\projects\my-llvm\clang\lib\AST\Interp\ByteCodeExprGen.cpp @ 1827] 
06 00000066`04580e40 00007ff6`55eb7023     clang!clang::interp::ByteCodeExprGen<clang::interp::EvalEmitter>::visitDecl+0x8e [C:\projects\my-llvm\clang\lib\AST\Interp\ByteCodeExprGen.cpp @ 1772] 
07 00000066`04580f30 00007ff6`55d18d54     clang!clang::interp::EvalEmitter::interpretDecl+0x33 [C:\projects\my-llvm\clang\lib\AST\Interp\EvalEmitter.cpp @ 39] 
08 00000066`04580f90 00007ff6`55633abf     clang!clang::interp::Context::evaluateAsInitializer+0xf4 [C:\projects\my-llvm\clang\lib\AST\Interp\Context.cpp @ 74] 
09 00000066`04581290 00007ff6`553b4398     clang!clang::Expr::EvaluateAsInitializer+0x28f [C:\projects\my-llvm\clang\lib\AST\ExprConstant.cpp @ 15545] 
0a 00000066`04581880 00007ff6`553b4744     clang!clang::VarDecl::evaluateValueImpl+0x148 [C:\projects\my-llvm\clang\lib\AST\Decl.cpp @ 2555] 
0b 00000066`04581940 00007ff6`537e94fc     clang!clang::VarDecl::checkForConstantInitialization+0xe4 [C:\projects\my-llvm\clang\lib\AST\Decl.cpp @ 2625] 
0c 00000066`04581980 00007ff6`537f8109     clang!clang::Sema::CheckCompleteVariableDeclaration+0xddc [C:\projects\my-llvm\clang\lib\Sema\SemaDecl.cpp @ 14315] 
0d 00000066`04582770 00000000`00000000     clang!clang::Sema::AddInitializerToDecl+0x2669 [C:\projects\my-llvm\clang\lib\Sema\SemaDecl.cpp @ 13712]

In CheckArrayInitialized BasePtr.atIndex(I).isInitialized() returns false, because InitMap does not exist. And it seems that BasePtr points to a different object, not the one which corresponds to StringLiteral (at step 2). This new interpreter does not use clang's AST, so it becomes difficult to understand what's happening. Any help would be appreciated. cc @tbaeder.

cor3ntin accepted this revision.Aug 25 2023, 4:59 AM

I'm happy punting the new interpreter to a subsequent PR, maybe there are unresolved issues with string literals?
Anyway, we don't have to scope creep further, LGTM

Thanks for working on this!

This revision is now accepted and ready to land.Aug 25 2023, 4:59 AM

And it seems that BasePtr points to a different object, not the one which corresponds to StringLiteral (at step 2).

If I understand everything correctly, then in visitGlobalInitializer, when we return from visitInitializer our this->Locals becomes empty. So this->emitCheckGlobalCtor(Init) fails, because it sees are elements are uninitialized.

Thanks for approval! Let me know if I should report my observations about new constexpr interpreter somewhere else.

RIscRIpt marked an inline comment as done.Aug 25 2023, 5:14 AM
RIscRIpt updated this revision to Diff 553444.Aug 25 2023, 5:32 AM

Rebased onto main, fixed commit messages, fixed formatting, re-run lit for clang/test

@RIscRIpt Do you need further help on this patch? You have commit access, right?
(I'm trying to make sure things don't fall through the cracks as we move to github)

@cor3ntin, thanks for asking. No, I do not have access. Please merge. Commits should have correct email and name.

Oh! I should have asked sooner. Will do! Thanks

Hum. before I do

  • I think the commit message could be more explicit as to what the patch does ("Add support of Windows Trace Logging macros" is a bit vague)
  • Do we need a release note ?

Hum. before I do

  • I think the commit message could be more explicit as to what the patch does ("Add support of Windows Trace Logging macros" is a bit vague)
  • Do we need a release note ?

I agree that single commit message is vague. That's why I submitted two separate commits with detailed messages (the first one has some details in body).

I don't think we need release notes, because it's a bug fix.

P.S. I don't have access to PC until next week, I am okay if you adjust commit messages in a way you want.

cor3ntin updated this revision to Diff 555712.Sep 4 2023, 5:21 AM

Add release note

@RIscRIpt I added release notes, let me know if you are happy with everything before i land

Looks good. Thanks!

This revision was landed with ongoing or failed builds.Sep 4 2023, 7:55 AM
This revision was automatically updated to reflect the committed changes.