Skip to content

Commit 10e2c45

Browse files
committed
Add new C++ API for variant parts
This patch adds new wrapper functions of DIBuilder methods to let gnat-llvm create variant parts.
1 parent 73365e3 commit 10e2c45

File tree

4 files changed

+136
-0
lines changed

4 files changed

+136
-0
lines changed

llvm-interface/check_for_llvm_apis.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ api_test HAVE_TYPE_FN_SCOPE "void call(DebugInfoFinder *f, DILocalVariable *v) {
4242
# Test that checks if sizes and offsets can be dynamic.
4343
api_test HAVE_DYNAMIC_OFFSETS "void call(DIBuilder *b) { b->createMemberType(nullptr, StringRef(), nullptr, 0, nullptr, 0, nullptr, DINode::FlagZero, nullptr); }"
4444

45+
# Test whether multiple members can be included in a variant.
46+
api_test HAVE_MULTI_MEMBER_VARIANT "void call(DIBuilder *b) { b->createVariantMemberType(nullptr, DINodeArray(), (Constant*)nullptr, (DIType*)nullptr); }"
47+
4548
for def in $haves; do
4649
echo "#define GNAT_LLVM_$def"
4750
done > obj/tmp-gnat-llvm-config.h

llvm-interface/gnatllvm-wrapper.adb

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -927,6 +927,19 @@ package body GNATLLVM.Wrapper is
927927
return Types_Can_Have_Dynamic_Offsets_C /= 0;
928928
end Types_Can_Have_Dynamic_Offsets;
929929

930+
---------------------------------------------
931+
-- Types_Can_Have_Multiple_Variant_Members --
932+
---------------------------------------------
933+
934+
function Types_Can_Have_Multiple_Variant_Members return Boolean
935+
is
936+
function Types_Can_Have_Multiple_Variant_Members_C return LLVM_Bool
937+
with Import => True, Convention => C,
938+
External_Name => "Types_Can_Have_Multiple_Variant_Members";
939+
begin
940+
return Types_Can_Have_Multiple_Variant_Members_C /= 0;
941+
end Types_Can_Have_Multiple_Variant_Members;
942+
930943
function Create_Global_Variable_Declaration
931944
(Builder : DI_Builder_T;
932945
Scope : Metadata_T;
@@ -984,4 +997,54 @@ package body GNATLLVM.Wrapper is
984997
unsigned (Elements'Length));
985998
end Replace_Composite_Elements;
986999

1000+
-------------------------
1001+
-- Create_Variant_Part --
1002+
-------------------------
1003+
1004+
function Create_Variant_Part
1005+
(Builder : DI_Builder_T;
1006+
Discriminator : Metadata_T;
1007+
Elements : Metadata_Array) return Metadata_T
1008+
is
1009+
function Create_Variant_Part_C
1010+
(Builder : DI_Builder_T;
1011+
Discriminator : Metadata_T;
1012+
Elements : System.Address;
1013+
Num_Elements : unsigned) return Metadata_T
1014+
with Import => True, Convention => C,
1015+
External_Name => "Create_Variant_Part";
1016+
begin
1017+
return Create_Variant_Part_C (Builder, Discriminator,
1018+
Elements'Address,
1019+
unsigned (Elements'Length));
1020+
end Create_Variant_Part;
1021+
1022+
---------------------------
1023+
-- Create_Variant_Member --
1024+
---------------------------
1025+
1026+
function Create_Variant_Member
1027+
(Builder : DI_Builder_T;
1028+
Elements : Metadata_Array;
1029+
Discriminants : Word_Array) return Metadata_T
1030+
is
1031+
function Create_Variant_Member_C
1032+
(Ctx : Context_T;
1033+
Builder : DI_Builder_T;
1034+
Elements : System.Address;
1035+
Num_Elements : unsigned;
1036+
Discriminants : System.Address;
1037+
Num_Discriminants : unsigned) return Metadata_T
1038+
with Import => True, Convention => C,
1039+
External_Name => "Create_Variant_Member";
1040+
begin
1041+
return Create_Variant_Member_C
1042+
(Get_Global_Context,
1043+
Builder,
1044+
Elements'Address,
1045+
unsigned (Elements'Length),
1046+
Discriminants'Address,
1047+
unsigned (Discriminants'Length));
1048+
end Create_Variant_Member;
1049+
9871050
end GNATLLVM.Wrapper;

llvm-interface/gnatllvm-wrapper.ads

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,10 @@ package GNATLLVM.Wrapper is
565565
-- Return true if the LLVM contains the patch that allows types to
566566
-- have dynamic offsets and sizes.
567567

568+
function Types_Can_Have_Multiple_Variant_Members return Boolean;
569+
-- Return true if the LLVM contains the patch that allows types to
570+
-- have multiple members in a variant part.
571+
568572
function Create_Global_Variable_Declaration
569573
(Builder : DI_Builder_T;
570574
Scope : Metadata_T;
@@ -585,4 +589,18 @@ package GNATLLVM.Wrapper is
585589
-- Wrapper for DIBuilder::replaceArrays that only allows updating
586590
-- the elements of a composite type.
587591

592+
function Create_Variant_Part
593+
(Builder : DI_Builder_T;
594+
Discriminator : Metadata_T;
595+
Elements : Metadata_Array) return Metadata_T;
596+
-- A wrapper for an LLVM DIBuilder method that creates a variant
597+
-- part.
598+
599+
function Create_Variant_Member
600+
(Builder : DI_Builder_T;
601+
Elements : Metadata_Array;
602+
Discriminants : Word_Array) return Metadata_T;
603+
-- A wrapper for an LLVM DIBuilder method that creates a variant
604+
-- member.
605+
588606
end GNATLLVM.Wrapper;

llvm-interface/llvm_wrapper.cc

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1549,6 +1549,17 @@ Types_Can_Have_Dynamic_Offsets ()
15491549
#endif
15501550
}
15511551

1552+
extern "C"
1553+
bool
1554+
Types_Can_Have_Multiple_Variant_Members ()
1555+
{
1556+
#ifdef GNAT_LLVM_HAVE_MULTI_MEMBER_VARIANT
1557+
return true;
1558+
#else
1559+
return false;
1560+
#endif
1561+
}
1562+
15521563
extern "C"
15531564
LLVMMetadataRef Create_Global_Variable_Declaration(
15541565
LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
@@ -1576,3 +1587,44 @@ LLVMMetadataRef Replace_Composite_Elements(
15761587
// T might have been modified by replaceArrays.
15771588
return wrap(T);
15781589
}
1590+
1591+
extern "C"
1592+
LLVMMetadataRef Create_Variant_Part(
1593+
LLVMDIBuilderRef Builder, LLVMMetadataRef Discriminator,
1594+
LLVMMetadataRef *Elements, unsigned NumElements) {
1595+
DIDerivedType *Disc = Discriminator ? unwrap<DIDerivedType>(Discriminator) : nullptr;
1596+
auto Elems = unwrap(Builder)->getOrCreateArray({unwrap(Elements), NumElements});
1597+
1598+
return wrap(unwrap(Builder)->createVariantPart(
1599+
nullptr, {}, nullptr, 0, 0, 0, DINode::FlagZero,
1600+
Disc, Elems));
1601+
}
1602+
1603+
extern "C"
1604+
LLVMMetadataRef Create_Variant_Member(
1605+
LLVMContext *Context, LLVMDIBuilderRef Builder,
1606+
LLVMMetadataRef *Elements, unsigned NumElements,
1607+
uint64_t *Discriminants, unsigned NumDiscriminants) {
1608+
#ifdef GNAT_LLVM_HAVE_MULTI_MEMBER_VARIANT
1609+
auto Elems = unwrap(Builder)->getOrCreateArray({unwrap(Elements), NumElements});
1610+
Constant *D = nullptr;
1611+
// Note that this small optimization is actually required: when
1612+
// adding support for discriminant lists to LLVM, I did not realize
1613+
// that ConstantDataArray::get will return a ConstantAggregateZero
1614+
// when possible; and so the DWARF generation code does not handle
1615+
// this case. If a variant uses "when 0", this will result in a
1616+
// discriminant array of {0, 0}, which would then be ignored by the
1617+
// DWARF writer. This optimization works around this oddity to
1618+
// provide correct DWARF output.
1619+
if (NumDiscriminants == 2 && Discriminants[0] == Discriminants[1]) {
1620+
D = ConstantInt::get (Type::getInt64Ty (*Context), Discriminants[0]);
1621+
} else if (NumDiscriminants > 0) {
1622+
ArrayRef<uint64_t> Vals(Discriminants, NumDiscriminants);
1623+
D = ConstantDataArray::get(*Context, Vals);
1624+
}
1625+
return wrap(unwrap(Builder)->createVariantMemberType(nullptr, Elems, D, nullptr));
1626+
#else
1627+
// This should never be called in this situation.
1628+
assert(0);
1629+
#endif
1630+
}

0 commit comments

Comments
 (0)