[cfe-dev] [Proposal]: Fast non-portable extension to retrieve a type name from a pointer as a GV: __builtin_type_name(T* Ptr, [int Style])

via cfe-dev cfe-dev at lists.llvm.org
Mon Sep 3 14:00:16 PDT 2018


I put together a very very minimal example of what it produces, (the 
prefix will be `__builtin` instead of `__os`, this is just an example
built with a toolchain where this was just an extension in a personal
fork of Clang).

WIth ELF target, all strings end up in `.rodata`. Tiny test case below,
includes omitted for brevity.



Minimal Test Case
^^^^^^^^^^^^^^^^^

class MyType
{
public:
	template <typename T>
	auto CallFunc(const T& TheFun) {
		auto StrStk = TheFun();
		return new decltype(StrStk)(StrStk);
	}

	MyType()
	{
		auto LocalType = [](){ return std::string{"foo"}; };
		OSLogger Log{"tiny_example"};

		Log.info(
			"\n{0}\n{1}\n{2}\n{3}\n{4}\n{5}\n{6}\n{7}",
			__os_type_name((std::vector<std::string>*)nullptr),
			__os_type_name(&LocalType, 0x1),
			__os_type_name(CallFunc(LocalType), 0x1),
			__os_type_name(&Log, 0x4),
			__os_type_name(&LocalType, 0x8),
			__os_type_name(&LocalType),
			__os_type_name(this, 0x4),
			__os_type_name(this, 0)
		);
	}
};

int main(int argc, const char** argv)
{
	MyType M{};
}



Runtime
^^^^^^^

[tiny_example           ][INFO   ]:
	std::vector<std::string>
	(lambda at /q/src/test_os_type_name/main.cc:46:20)
	std::__1::basic_string<char>
	OSLogger
	(lambda at /q/src/test_os_type_name/main.cc:46:20)
	class (lambda at /q/src/test_os_type_name/main.cc:46:20)
	MyType
	class MyType


Hopefully that demonstrates what I had in mind. All strings are unique
within `.rodata`, there are no heavy structures that would usually be
assosciated with RTTI, in fact this is built without RTTI or exceptions.

I overused auto a bit intentionally in this case. An example from a more
complex application which uses a Postgres client in C++ and a lot of 
generics can print out types like these (newlines inserted by me):

"std::__1::tuple<pg::internal::ColumnImpl<pg::internal::oid_info<pg:
:internal::tag [1043]>, PGMeta::VarChar>, pg::internal::ColumnImpl<pg::internal
::oid_info<pg::internal::tag [1043]>, PGMeta::VarChar> >"

Thank you.
- Kristina


On 03/09/2018 at 5:28 PM, "Hal Finkel" <hfinkel at anl.gov> wrote:
>
>[+Chandler]
>
>Hi, Kristina, can you provide a couple of examples of what this 
>would
>print for various cases?
>
> -Hal
>
>
>On 09/03/2018 09:40 AM, via cfe-dev wrote:
>> The concept itself is pretty trivial, the builtin takes one or 
>two arguments, one of which
>> has to be a pointer to an arbitrary type, this makes it 
>particularly useful with C++
>> auto declarations or even printing the type by simply casting a 
>null pointer to
>> the type in question. It's qualifiers are retained for the sake 
>of printing them
>> depending on the requested style.
>>
>> Implementation
>> ^^^^^^^^^^^^^^
>>
>> const char* TypeName =  __builtin_type_name(T* Ptr, [int Style])
>>
>> After validating either 1 or 2 argument form (ie. Pointed to 
>type, and whether it's a 
>> record declaration), SemaChecking will set the return type to 
>TheCall->setType(
>> Context.getPointerType(Context.CharTy.withConst())) leaving it 
>for Clang's CodeGen
>> to deal with.
>>
>> Second argument is used to control the output format in form of 
>a bitmask
>> passed down to PrintingPolicy (as I port this I will decouple 
>the values so the 
>> builtin's behavior isn't dependent on further changes in 
>PrintingPolicy. At 
>> which point the type is retrieved using `getAsString` and stored 
>in the CGM 
>> with `GetAddrOfConstantCString` allowing coalescing of those 
>strings later 
>> during linking. as it's cast to a Int8Ptr.
>>
>> This is all done in Clang without needing to add anything to the 
>LLVM core.
>>
>> Things left to do before submitting for code review
>> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>> * There is no test coverage, so I need to write up a test file, 
>comprehensively
>>   testing cases I haven't considered before like Objective-C 
>pointers, any
>>   pointer to a special Clang type that may behave unexpectedly, 
>complex
>>   C++ templates (or simple ones, was my main use of it). Target 
>is IR since
>>   Clang fully lowers it, so in theory it's platform agnostic 
>providing there is
>>   enough space (the original use was for Embedded C++ with no 
>RTTI.
>> * While this is out of scope, a GUID buffer as a a style would 
>provide a form
>>   type IDs in absence of RTTI or alternatively smaller types 
>like u32 or u16
>>   (aimed at single module builds where they can remain unique, 
>ie. embedded
>>   systems with a kernel using those to represent kernel object 
>types).
>>
>> Rationale
>> ^^^^^^^^^
>> It's clear that this functionality is desired outside of 
>embedded domain,
>> typically with hacks involving a lambda and __PRETTY_FUNCTION__, 
>on case
>> being in `lib/Support/TypeName.h` in LLVMSupport. Many non-
>portable hacks
>> that depend on compiler versions exist. This doesn't aim to be 
>portable,
>> just to be compact, not have a runtime cost, and provide this 
>information
>> either for debugging or even for more practical reasons.
>>
>> I wanted to find out if there was interest in this kind of thing 
>since
>> I have developed a variety of different useful and not so useful 
>extensions,
>> originally for embedded use but I want to upstream them for 
>general use,
>> I want to know what the consensus is on 1) This particular 
>extension
>> 2). Further extensions that were originally developed for 
>embedded use
>> but have turned out to be useful in a lot of contexts where you 
>are willing
>> to sacrifice portability  (now with `__has_builtin` this is 
>extremely easy to 
>> test for and fallback on something else).
>>
>> On the other hand it's a lot to do overall so I would prefer to 
>get a consensus
>> whether each feature (even this small one) is worth cleaning up 
>and putting
>> up for code review, since I understand that something like 
>builtin bloat
>> or non portability may be of concern. As for the formal name I'd 
>like to call
>> it extensions for Embedded C++ 2 gating it behind an opt-in flag 
>such as
>> `-fecxx2-extensions`.
>>
>> Other things involve limited reflection retrieving the bare 
>minimum that's
>> needed, a llvm::formatv style formatter accelerator, getting 
>names of record
>> scope at different levels with 0 being similar to the desired 
>__CLASSNAME__ 
>> macro (at least by some).
>>
>> Looking forward to any feedback whether positive or negative.
>> Thank you for your time.
>> - Kristina
>>
>> _______________________________________________
>> cfe-dev mailing list
>> cfe-dev at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>
>-- 
>Hal Finkel
>Lead, Compiler Technology and Programming Languages
>Leadership Computing Facility
>Argonne National Laboratory




More information about the cfe-dev mailing list