Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion include/ifc/abstract-sgraph.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ namespace ifc {
Destructor, // A destructor declaration.
Reference, // A reference to a declaration from a given module.
Using, // A using declaration. FIXME: See bug https://github.com/microsoft/ifc-spec/issues/122
UnusedSort0, // Empty slot
Prolongation, // An out-of-home-scope definition for an entity previously declared in its home scope.
Friend, // A friend declaration. FIXME: See bug https://github.com/microsoft/ifc-spec/issues/123
Expansion, // A pack-expansion of a declaration
DeductionGuide, // C(T) -> C<U>
Expand Down Expand Up @@ -2448,6 +2448,13 @@ namespace ifc {
bool is_hidden{}; // Is this using-declaration hidden?
};

struct ProlongationDecl : Tag<DeclSort::Prolongation> {
Identity<NameIndex> identity{};
DeclIndex enclosing_scope{}; // Enclosing scope of this declaration.
DeclIndex home_scope{}; // The scope to which this decl belongs.
DeclIndex original_decl{}; // The original decl in home_scope.
};

struct FriendDecl : Tag<DeclSort::Friend> {
ExprIndex index{}; // The expression representing a reference to the declaration.
// Note: most of the time this is a NamedDeclExpression but it
Expand Down Expand Up @@ -3189,6 +3196,7 @@ namespace ifc {
Attributes, // attributes associated with a declaration
Deprecated, // deprecation message.
DeductionGuides, // Declared deduction guides associated with a class
Prolongations, // Prolongation declarations associated with a scope
Count,
};

Expand Down Expand Up @@ -3279,6 +3287,7 @@ namespace ifc {
struct Attributes : AssociatedTrait<SyntaxIndex, SyntaxIndex>, TraitTag<TraitSort::Attributes> {};
struct Deprecated : AssociatedTrait<DeclIndex, TextOffset>, TraitTag<TraitSort::Deprecated> {};
struct DeductionGuides : AssociatedTrait<DeclIndex, DeclIndex>, TraitTag<TraitSort::DeductionGuides> {};
struct Prolongations : AssociatedTrait<DeclIndex, Sequence<Declaration>>, TraitTag<TraitSort::Prolongations> {};
} // namespace symbolic::trait

// Msvc specific traits. Should they be in their own namespace, like symbolic::MsvcTrait?
Expand Down Expand Up @@ -3431,6 +3440,7 @@ namespace ifc {
// semantics of the current TU.
PartitionSummaryData debug_records; // Implementation-specific data for debugging.
PartitionSummaryData gmf_specializations; // Decl-reachable template specializations in the global module fragment.
PartitionSummaryData prolongations; // An association between scopes and prolongation declarations.

// Facilities for iterating over the ToC as a sequence of partition summaries.
// Note: the use of reinterpret_cast below is avoidable. One way uses
Expand Down
2 changes: 2 additions & 0 deletions include/ifc/operators.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ namespace ifc {
MsvcConfusedTemporaryArray, // The backing temporary array for a std::initializer_list
MsvcConfusedDependentNestedDecl, // The parser saw a nested-name as part of a declaration of a dependent expression (e.g. 'friend void X<T>::mf()') and 'mf' is the
// named declaration here.
MsvcConfusedTemplateAliasSubstitution, // Represents a non-type template argument substitution inside of a template alias specialization. This is unique from 'MsvcConfusedSubstitution'
// above due to C++ semantics requiring this type of substitution to be transparent.

Last
};
Expand Down
1 change: 1 addition & 0 deletions include/ifc/source-word.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ namespace ifc {
MsvcCastTargetType, // Binding of a resolve type in a cast expression. FIXME: to be removed along with
// other YACC oddities.
MsvcTemplateId, // A reference to a known template template specialization.
MsvcResolvedExpression,// Binding of a resolved expression
};

enum class Operator : uint16_t {
Expand Down
10 changes: 7 additions & 3 deletions include/ifc/version.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#define IFC_VERSION_INCLUDED

#include <cstdint>

#include <compare>

namespace ifc {
Expand All @@ -18,11 +17,16 @@ namespace ifc {
auto operator<=>(const FormatVersion&) const = default;
};

// Minimum and current version components.
inline constexpr Version MajorVersion { 0 };
inline constexpr Version MinimumMinorVersion { 43 };
inline constexpr Version CurrentMinorVersion { 44 };

// Minimum supported file format version
inline constexpr FormatVersion MinimumFormatVersion{Version{0}, Version{43}};
inline constexpr FormatVersion MinimumFormatVersion{MajorVersion, MinimumMinorVersion};

// The current version of file format emitted by the toolset
inline constexpr FormatVersion CurrentFormatVersion = MinimumFormatVersion;
inline constexpr FormatVersion CurrentFormatVersion{MajorVersion, CurrentMinorVersion};
} // namespace ifc

#endif // IFC_VERSION_INCLUDED
18 changes: 15 additions & 3 deletions samples/sgraph-js/sgraph/decls.js
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ class PartialSpecializationDecl {
this.home_scope = new DeclIndex(reader);
this.chart = new ChartIndex(reader);
this.entity = new ParameterizedEntity(reader);
this.specialization_info = reader.read_uint32();
this.specialization_form = new SpecFormIndex(reader);
this.basic_spec = new BasicSpecifiers(reader);
this.access = new Access(reader);
this.properties = new ReachableProperties(reader);
Expand All @@ -219,7 +219,7 @@ class SpecializationDecl {
static partition_name = "decl.specialization";

constructor(reader) {
this.specialization_info = reader.read_uint32();
this.specialization_form = new SpecFormIndex(reader);
this.decl = new DeclIndex(reader);
this.sort = new SpecializationSort(reader);
this.pad1 = new StructPadding(reader);
Expand Down Expand Up @@ -365,6 +365,17 @@ class UsingDecl {
}
}

class ProlongationDecl {
static partition_name = "decl.prolongation";

constructor(reader) {
this.identity = new IdentityNameIndex(reader);
this.enclosing_scope = new DeclIndex(reader);
this.home_scope = new DeclIndex(reader);
this.original_decl = new DeclIndex(reader);
}
}

class FriendDecl {
static partition_name = "decl.friend";

Expand Down Expand Up @@ -515,6 +526,8 @@ function symbolic_for_decl_sort(sort) {
return ReferenceDecl;
case DeclIndex.Sort.Using:
return UsingDecl;
case DeclIndex.Sort.Prolongation:
return ProlongationDecl;
case DeclIndex.Sort.Friend:
return FriendDecl;
case DeclIndex.Sort.Expansion:
Expand All @@ -535,7 +548,6 @@ function symbolic_for_decl_sort(sort) {
return SegmentDecl;
case DeclIndex.Sort.VendorExtension:
return VendorDecl;
case DeclIndex.Sort.UnusedSort0:
default:
console.error(`Bad sort: ${sort}`);
return null;
Expand Down
29 changes: 29 additions & 0 deletions samples/sgraph-js/sgraph/resolve.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ class Resolver {
this.reader = reader;
this.toc = toc;
this.string_table = string_table;
this.msvc_traits = this.associated_trait_table(AssociatedMsvcTraits);
}

decl_index_in_bounds(index) {
Expand Down Expand Up @@ -166,6 +167,34 @@ class Resolver {
}
return elms;
}

resolve_spec_form(form) {
const partition = this.toc.partition_by_name(form.T.partition_name);
return this.read(form.T, form.value);
}

associated_trait_table(T) {
const partition = this.toc.partition_by_name(T.partition_name);
var elms = new Array();
if (partition == undefined)
return elms;
var offset = partition.tell(0);
for (var i = 0; i < partition.cardinality; ++i) {
var k = this.offset_read(T.K, offset);
var v = new T.V(this.reader);
elms.push({ key: k, value: v });
offset += partition.entry_size;
}
return elms;
}

associated_trait_index(key, table) {
var idx = lower_bound(table, e => [...Object.values(key)] <= [...Object.values(e.key)]);
if (idx < table.length && [...Object.values(key)].equal([...Object.values(table[idx].key)])) {
return table[idx].value;
}
return undefined;
}
}

class ResolvedLocus {
Expand Down
84 changes: 80 additions & 4 deletions samples/sgraph-js/sgraph/sgraph.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// Copyright Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

// Based on IFC specification 0.43.
// Based on IFC specification 0.44.
function implemented_ifc_version() {
return new Version(0, 43);
return new Version(0, 44);
}

function ifc_version_compatible(version) {
Expand Down Expand Up @@ -69,7 +69,7 @@ class DeclIndex {
Destructor: 19, // A destructor declaration.
Reference: 20, // A reference to a declaration from a given module.
Using: 21, // A using declaration. FIXME: See bug https://github.com/microsoft/ifc-spec/issues/122
UnusedSort0: 22, // Empty slot
Prolongation: 22, // An out-of-home-scope definition for an entity previously declared in its home scope.
Friend: 23, // A friend declaration. FIXME: See bug https://github.com/microsoft/ifc-spec/issues/123
Expansion: 24, // A pack-expansion of a declaration
DeductionGuide: 25, // C(T) -> C<U>
Expand Down Expand Up @@ -859,4 +859,80 @@ class StructPadding {
constructor(reader) {
this.value = reader.read_uint8();
}
}
}

// Symbolic representation of a specialization request, whether implicit or explicit.
class SpecializationForm {
static partition_name = "form.spec";

constructor(reader) {
this.template_decl = new DeclIndex(reader);
this.arguments = new ExprIndex(reader);
}
}

class SpecFormIndex {
constructor(reader) {
this.T = SpecializationForm;
this.value = reader.read_uint32();
}
}

// MSVC-specific vendor traits.
class MsvcVendorTraits {
static partition_name = ".msvc.trait.vendor-traits";

static Values = {
None: 0,
ForceInline: 1 << 0, // __forceinline function
Naked: 1 << 1, // __declspec(naked)
NoAlias: 1 << 2, // __declspec(noalias)
NoInline: 1 << 3, // __declspec(noinline)
Restrict: 1 << 4, // __declspec(restrict)
SafeBuffers: 1 << 5, // __declspec(safebuffers)
DllExport: 1 << 6, // __declspec(dllexport)
DllImport: 1 << 7, // __declspec(dllimport)
CodeSegment: 1 << 8, // __declspec(code_seg("segment"))
NoVtable: 1 << 9, // __declspec(novtable) for a class type.
IntrinsicType: 1 << 10, // __declspec(intrin_type)
EmptyBases: 1 << 11, // __declspec(empty_bases)
Process: 1 << 12, // __declspec(process)
Allocate: 1 << 13, // __declspec(allocate("segment"))
SelectAny: 1 << 14, // __declspec(selectany)
Comdat: 1 << 15,
Uuid: 1 << 16, // __declspec(uuid(....))
NoCtorDisplacement: 1 << 17, // #pragma vtordisp(0)
DefaultCtorDisplacement: 1 << 18, // #pragma vtordisp(1)
FullCtorDisplacement: 1 << 19, // #pragma vtordisp(2)
NoSanitizeAddress: 1 << 20, // __declspec(no_sanitize_address)
NoUniqueAddress: 1 << 21, // '[[msvc::no_unique_address]]'
NoInitAll: 1 << 22, // __declspec(no_init_all)
DynamicInitialization: 1 << 23, // Indicates that this entity is used for implementing
// aspects of dynamic initialization.
LexicalScopeIndex: 1 << 24, // Indicates this entity has a local lexical scope index associated with it.
ResumableFunction: 1 << 25, // Indicates this function was a transformed coroutine function.
PersistentTemporary: 1 << 26, // a c1xx-ism which will create long-lived temporary symbols when expressions
// need their result to live beyond the full expression, e.g. lifetime
// extended temporaries.
IneligibleForNRVO: 1 << 27, // a c1xx-ism in which the front-end conveys to the back-end that a particular
// function cannot utilize NRVO on this function. This is important due to the
// MSVC C++ calling convention which passes UDTs on the stack as a hidden parameter
// to functions returning that type.
MultiBytePTMRep: 1 << 28 // a c1xx-ism which indicates that the pointer-to-member representation for a class
// type is a generalized multi-byte representation for ABI purposes.
};

constructor(reader) {
this.value = reader.read_uint32();
}
}

class AssociatedTrait {
constructor(part, K, V) {
this.partition_name = part;
this.K = K;
this.V = V;
}
}

const AssociatedMsvcTraits = new AssociatedTrait(MsvcVendorTraits.partition_name, DeclIndex, MsvcVendorTraits);
30 changes: 30 additions & 0 deletions samples/sgraph-js/sgraph/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,34 @@ function debounce(func, timeout = 300) {
clearTimeout(timer);
timer = setTimeout(() => { func.apply(this, args); }, timeout);
};
}

function binary_search(array, pred) {
let low = -1;
let high = array.length;
while (low + 1 < high) {
const mid = low + ((high - low) >> 1);
if (pred(array[mid])) {
high = mid;
} else {
low = mid;
}
}
return high;
}

// 'pred' should model "val <= x".
function lower_bound(array, pred) {
return binary_search(array, pred);
}

// Useful array prototypes.
Array.prototype.equal = function(other) {
if (this.length != other.length)
return false;
for (var i = 0; i < this.length; ++i) {
if (this[i] != other[i])
return false;
}
return true;
}
19 changes: 18 additions & 1 deletion samples/sgraph-js/ui/ifc-explorer.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,13 @@ class IFCExplorerJSONReplacer {
return resolved_seq;
}

static replace_spec_form_index(index) {
if (index.value == 0)
return "SpecFormIndex{null}";
const spec_form = sgraph.resolver.resolve_spec_form(index);
return { template_decl: spec_form.template_decl, arguments: spec_form.arguments };
}

static replace_scope_index(index) {
if (null_scope(index)) {
return { scope_index: index.value, decls: [] };
Expand Down Expand Up @@ -184,6 +191,8 @@ function ifc_explorer_json_replacer(key, value) {
return IFCExplorerJSONReplacer.replace_locus(value);
if (value instanceof ScopeIndex)
return IFCExplorerJSONReplacer.replace_scope_index(value);
if (value instanceof SpecFormIndex)
return IFCExplorerJSONReplacer.replace_spec_form_index(value);
if (value instanceof Operator)
return IFCExplorerJSONReplacer.replace_operator(value);
if (value instanceof HeapSequence)
Expand All @@ -198,6 +207,10 @@ function ifc_explorer_json_replacer(key, value) {
return IFCExplorerJSONReplacer.generic_bitset_to_string(FunctionTraits, value);
if (value instanceof FunctionTypeTraits)
return IFCExplorerJSONReplacer.generic_bitset_to_string(FunctionTypeTraits, value);
if (value instanceof ObjectTraits)
return IFCExplorerJSONReplacer.generic_bitset_to_string(ObjectTraits, value);
if (value instanceof MsvcVendorTraits)
return IFCExplorerJSONReplacer.generic_bitset_to_string(MsvcVendorTraits, value);
if (value instanceof Qualifier)
return IFCExplorerJSONReplacer.generic_bitset_to_string(Qualifier, value);
if (value instanceof Phases)
Expand Down Expand Up @@ -252,7 +265,11 @@ function set_ifc_explorer_selected_decl(index, from_history, skip_navigation) {
ifc_explorer.decls.index_edit.value = index.index;

const symbolic = symbolic_for_decl_sort(index.sort);
const symbolic_decl = sgraph.resolver.read(symbolic, index.index);
var symbolic_decl = sgraph.resolver.read(symbolic, index.index);
const msvc_traits = sgraph.resolver.associated_trait_index(index, sgraph.resolver.msvc_traits);
if (msvc_traits != undefined) {
symbolic_decl.msvc_traits = msvc_traits;
}
const json_str = JSON.stringify(symbolic_decl, ifc_explorer_json_replacer, 2);
const container = document.createElement("pre");
const sort = sort_to_string(DeclIndex, index.sort);
Expand Down
2 changes: 1 addition & 1 deletion samples/sgraph-js/ui/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ class Options {
case DeclIndex.Sort.VendorExtension:
return 'tan';
case DeclIndex.Sort.DefaultArgument:
case DeclIndex.Sort.UnusedSort0:
case DeclIndex.Sort.Prolongation:
case DeclIndex.Sort.Count:
return 'black';
default:
Expand Down
3 changes: 2 additions & 1 deletion src/sgraph.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ namespace ifc {
{DeclSort::Destructor, "decl.destructor"},
{DeclSort::Reference, "decl.reference"},
{DeclSort::Using, "decl.using-declaration"},
{DeclSort::UnusedSort0, "decl.unused0"},
{DeclSort::Prolongation, "decl.prolongation"},
{DeclSort::Friend, "decl.friend"},
{DeclSort::Expansion, "decl.expansion"},
{DeclSort::DeductionGuide, "decl.deduction-guide"},
Expand Down Expand Up @@ -358,6 +358,7 @@ namespace ifc {
{TraitSort::Friends, "trait.friend"}, {TraitSort::Specializations, "trait.specialization"},
{TraitSort::Requires, "trait.requires"}, {TraitSort::Attributes, "trait.attribute"},
{TraitSort::Deprecated, "trait.deprecated"}, {TraitSort::DeductionGuides, "trait.deduction-guides"},
{TraitSort::Prolongations, "trait.prolongation"},
};

static_assert(retractible_by_key(traitsort_table));
Expand Down