From 35c18d4bb97abe16e5b3b52d927bb628fb5648ea Mon Sep 17 00:00:00 2001 From: Andrzej Janik Date: Wed, 9 Dec 2020 02:01:31 +0100 Subject: [PATCH] Add casts to convert PTX -> SPIRV builtins --- ptx/src/test/spirv_run/ntid.spvtxt | 20 +- .../test/spirv_run/stateful_ld_st_ntid.spvtxt | 34 ++-- .../stateful_ld_st_ntid_chain.spvtxt | 34 ++-- .../spirv_run/stateful_ld_st_ntid_sub.spvtxt | 46 +++-- ptx/src/translate.rs | 189 +++++++++--------- 5 files changed, 170 insertions(+), 153 deletions(-) diff --git a/ptx/src/test/spirv_run/ntid.spvtxt b/ptx/src/test/spirv_run/ntid.spvtxt index d1a3caa..acd69d7 100644 --- a/ptx/src/test/spirv_run/ntid.spvtxt +++ b/ptx/src/test/spirv_run/ntid.spvtxt @@ -12,16 +12,16 @@ OpEntryPoint Kernel %1 "ntid" %gl_WorkGroupSize OpDecorate %gl_WorkGroupSize BuiltIn WorkgroupSize %void = OpTypeVoid - %uint = OpTypeInt 32 0 - %v4uint = OpTypeVector %uint 4 -%_ptr_UniformConstant_v4uint = OpTypePointer UniformConstant %v4uint -%gl_WorkGroupSize = OpVariable %_ptr_UniformConstant_v4uint UniformConstant %ulong = OpTypeInt 64 0 - %33 = OpTypeFunction %void %ulong %ulong + %v3ulong = OpTypeVector %ulong 3 +%_ptr_Input_v3ulong = OpTypePointer Input %v3ulong +%gl_WorkGroupSize = OpVariable %_ptr_Input_v3ulong Input + %32 = OpTypeFunction %void %ulong %ulong %_ptr_Function_ulong = OpTypePointer Function %ulong + %uint = OpTypeInt 32 0 %_ptr_Function_uint = OpTypePointer Function %uint %_ptr_Generic_uint = OpTypePointer Generic %uint - %1 = OpFunction %void None %33 + %1 = OpFunction %void None %32 %9 = OpFunctionParameter %ulong %10 = OpFunctionParameter %ulong %25 = OpLabel @@ -41,9 +41,11 @@ %23 = OpConvertUToPtr %_ptr_Generic_uint %14 %13 = OpLoad %uint %23 OpStore %6 %13 - %16 = OpLoad %v4uint %gl_WorkGroupSize - %22 = OpCompositeExtract %uint %16 0 - %15 = OpCopyObject %uint %22 + %37 = OpLoad %v3ulong %gl_WorkGroupSize + %22 = OpCompositeExtract %ulong %37 0 + %38 = OpBitcast %ulong %22 + %16 = OpUConvert %uint %38 + %15 = OpCopyObject %uint %16 OpStore %7 %15 %18 = OpLoad %uint %6 %19 = OpLoad %uint %7 diff --git a/ptx/src/test/spirv_run/stateful_ld_st_ntid.spvtxt b/ptx/src/test/spirv_run/stateful_ld_st_ntid.spvtxt index c53ad51..bad44f4 100644 --- a/ptx/src/test/spirv_run/stateful_ld_st_ntid.spvtxt +++ b/ptx/src/test/spirv_run/stateful_ld_st_ntid.spvtxt @@ -12,16 +12,16 @@ OpEntryPoint Kernel %1 "stateful_ld_st_ntid" %gl_LocalInvocationID OpDecorate %gl_LocalInvocationID BuiltIn LocalInvocationId %void = OpTypeVoid - %uint = OpTypeInt 32 0 - %v4uint = OpTypeVector %uint 4 -%_ptr_Input_v4uint = OpTypePointer Input %v4uint -%gl_LocalInvocationID = OpVariable %_ptr_Input_v4uint Input + %ulong = OpTypeInt 64 0 + %v3ulong = OpTypeVector %ulong 3 +%_ptr_Input_v3ulong = OpTypePointer Input %v3ulong +%gl_LocalInvocationID = OpVariable %_ptr_Input_v3ulong Input %uchar = OpTypeInt 8 0 %_ptr_CrossWorkgroup_uchar = OpTypePointer CrossWorkgroup %uchar %56 = OpTypeFunction %void %_ptr_CrossWorkgroup_uchar %_ptr_CrossWorkgroup_uchar %_ptr_Function__ptr_CrossWorkgroup_uchar = OpTypePointer Function %_ptr_CrossWorkgroup_uchar + %uint = OpTypeInt 32 0 %_ptr_Function_uint = OpTypePointer Function %uint - %ulong = OpTypeInt 64 0 %_ptr_Function_ulong = OpTypePointer Function %ulong %_ptr_CrossWorkgroup_ulong = OpTypePointer CrossWorkgroup %ulong %1 = OpFunction %void None %56 @@ -57,25 +57,27 @@ %18 = OpCopyObject %ulong %19 %27 = OpConvertUToPtr %_ptr_CrossWorkgroup_uchar %18 OpStore %11 %27 - %29 = OpLoad %v4uint %gl_LocalInvocationID - %42 = OpCompositeExtract %uint %29 0 - %28 = OpCopyObject %uint %42 + %61 = OpLoad %v3ulong %gl_LocalInvocationID + %42 = OpCompositeExtract %ulong %61 0 + %62 = OpBitcast %ulong %42 + %29 = OpUConvert %uint %62 + %28 = OpCopyObject %uint %29 OpStore %6 %28 %31 = OpLoad %uint %6 - %61 = OpBitcast %uint %31 - %30 = OpUConvert %ulong %61 + %63 = OpBitcast %uint %31 + %30 = OpUConvert %ulong %63 OpStore %7 %30 %33 = OpLoad %_ptr_CrossWorkgroup_uchar %10 %34 = OpLoad %ulong %7 - %62 = OpBitcast %_ptr_CrossWorkgroup_uchar %33 - %63 = OpInBoundsPtrAccessChain %_ptr_CrossWorkgroup_uchar %62 %34 - %32 = OpBitcast %_ptr_CrossWorkgroup_uchar %63 + %64 = OpBitcast %_ptr_CrossWorkgroup_uchar %33 + %65 = OpInBoundsPtrAccessChain %_ptr_CrossWorkgroup_uchar %64 %34 + %32 = OpBitcast %_ptr_CrossWorkgroup_uchar %65 OpStore %10 %32 %36 = OpLoad %_ptr_CrossWorkgroup_uchar %11 %37 = OpLoad %ulong %7 - %64 = OpBitcast %_ptr_CrossWorkgroup_uchar %36 - %65 = OpInBoundsPtrAccessChain %_ptr_CrossWorkgroup_uchar %64 %37 - %35 = OpBitcast %_ptr_CrossWorkgroup_uchar %65 + %66 = OpBitcast %_ptr_CrossWorkgroup_uchar %36 + %67 = OpInBoundsPtrAccessChain %_ptr_CrossWorkgroup_uchar %66 %37 + %35 = OpBitcast %_ptr_CrossWorkgroup_uchar %67 OpStore %11 %35 %39 = OpLoad %_ptr_CrossWorkgroup_uchar %10 %45 = OpBitcast %_ptr_CrossWorkgroup_ulong %39 diff --git a/ptx/src/test/spirv_run/stateful_ld_st_ntid_chain.spvtxt b/ptx/src/test/spirv_run/stateful_ld_st_ntid_chain.spvtxt index 5ba889c..cc99aa0 100644 --- a/ptx/src/test/spirv_run/stateful_ld_st_ntid_chain.spvtxt +++ b/ptx/src/test/spirv_run/stateful_ld_st_ntid_chain.spvtxt @@ -12,16 +12,16 @@ OpEntryPoint Kernel %1 "stateful_ld_st_ntid_chain" %gl_LocalInvocationID OpDecorate %gl_LocalInvocationID BuiltIn LocalInvocationId %void = OpTypeVoid - %uint = OpTypeInt 32 0 - %v4uint = OpTypeVector %uint 4 -%_ptr_Input_v4uint = OpTypePointer Input %v4uint -%gl_LocalInvocationID = OpVariable %_ptr_Input_v4uint Input + %ulong = OpTypeInt 64 0 + %v3ulong = OpTypeVector %ulong 3 +%_ptr_Input_v3ulong = OpTypePointer Input %v3ulong +%gl_LocalInvocationID = OpVariable %_ptr_Input_v3ulong Input %uchar = OpTypeInt 8 0 %_ptr_CrossWorkgroup_uchar = OpTypePointer CrossWorkgroup %uchar %64 = OpTypeFunction %void %_ptr_CrossWorkgroup_uchar %_ptr_CrossWorkgroup_uchar %_ptr_Function__ptr_CrossWorkgroup_uchar = OpTypePointer Function %_ptr_CrossWorkgroup_uchar + %uint = OpTypeInt 32 0 %_ptr_Function_uint = OpTypePointer Function %uint - %ulong = OpTypeInt 64 0 %_ptr_Function_ulong = OpTypePointer Function %ulong %_ptr_CrossWorkgroup_ulong = OpTypePointer CrossWorkgroup %ulong %1 = OpFunction %void None %64 @@ -61,25 +61,27 @@ %26 = OpCopyObject %ulong %27 %35 = OpConvertUToPtr %_ptr_CrossWorkgroup_uchar %26 OpStore %18 %35 - %37 = OpLoad %v4uint %gl_LocalInvocationID - %50 = OpCompositeExtract %uint %37 0 - %36 = OpCopyObject %uint %50 + %69 = OpLoad %v3ulong %gl_LocalInvocationID + %50 = OpCompositeExtract %ulong %69 0 + %70 = OpBitcast %ulong %50 + %37 = OpUConvert %uint %70 + %36 = OpCopyObject %uint %37 OpStore %10 %36 %39 = OpLoad %uint %10 - %69 = OpBitcast %uint %39 - %38 = OpUConvert %ulong %69 + %71 = OpBitcast %uint %39 + %38 = OpUConvert %ulong %71 OpStore %11 %38 %41 = OpLoad %_ptr_CrossWorkgroup_uchar %15 %42 = OpLoad %ulong %11 - %70 = OpBitcast %_ptr_CrossWorkgroup_uchar %41 - %71 = OpInBoundsPtrAccessChain %_ptr_CrossWorkgroup_uchar %70 %42 - %40 = OpBitcast %_ptr_CrossWorkgroup_uchar %71 + %72 = OpBitcast %_ptr_CrossWorkgroup_uchar %41 + %73 = OpInBoundsPtrAccessChain %_ptr_CrossWorkgroup_uchar %72 %42 + %40 = OpBitcast %_ptr_CrossWorkgroup_uchar %73 OpStore %16 %40 %44 = OpLoad %_ptr_CrossWorkgroup_uchar %18 %45 = OpLoad %ulong %11 - %72 = OpBitcast %_ptr_CrossWorkgroup_uchar %44 - %73 = OpInBoundsPtrAccessChain %_ptr_CrossWorkgroup_uchar %72 %45 - %43 = OpBitcast %_ptr_CrossWorkgroup_uchar %73 + %74 = OpBitcast %_ptr_CrossWorkgroup_uchar %44 + %75 = OpInBoundsPtrAccessChain %_ptr_CrossWorkgroup_uchar %74 %45 + %43 = OpBitcast %_ptr_CrossWorkgroup_uchar %75 OpStore %19 %43 %47 = OpLoad %_ptr_CrossWorkgroup_uchar %16 %53 = OpBitcast %_ptr_CrossWorkgroup_ulong %47 diff --git a/ptx/src/test/spirv_run/stateful_ld_st_ntid_sub.spvtxt b/ptx/src/test/spirv_run/stateful_ld_st_ntid_sub.spvtxt index 3c215d4..32f2afb 100644 --- a/ptx/src/test/spirv_run/stateful_ld_st_ntid_sub.spvtxt +++ b/ptx/src/test/spirv_run/stateful_ld_st_ntid_sub.spvtxt @@ -12,16 +12,16 @@ OpEntryPoint Kernel %1 "stateful_ld_st_ntid_sub" %gl_LocalInvocationID OpDecorate %gl_LocalInvocationID BuiltIn LocalInvocationId %void = OpTypeVoid - %uint = OpTypeInt 32 0 - %v4uint = OpTypeVector %uint 4 -%_ptr_Input_v4uint = OpTypePointer Input %v4uint -%gl_LocalInvocationID = OpVariable %_ptr_Input_v4uint Input + %ulong = OpTypeInt 64 0 + %v3ulong = OpTypeVector %ulong 3 +%_ptr_Input_v3ulong = OpTypePointer Input %v3ulong +%gl_LocalInvocationID = OpVariable %_ptr_Input_v3ulong Input %uchar = OpTypeInt 8 0 %_ptr_CrossWorkgroup_uchar = OpTypePointer CrossWorkgroup %uchar %72 = OpTypeFunction %void %_ptr_CrossWorkgroup_uchar %_ptr_CrossWorkgroup_uchar %_ptr_Function__ptr_CrossWorkgroup_uchar = OpTypePointer Function %_ptr_CrossWorkgroup_uchar + %uint = OpTypeInt 32 0 %_ptr_Function_uint = OpTypePointer Function %uint - %ulong = OpTypeInt 64 0 %_ptr_Function_ulong = OpTypePointer Function %ulong %ulong_0 = OpConstant %ulong 0 %_ptr_CrossWorkgroup_ulong = OpTypePointer CrossWorkgroup %ulong @@ -63,43 +63,45 @@ %26 = OpCopyObject %ulong %27 %37 = OpConvertUToPtr %_ptr_CrossWorkgroup_uchar %26 OpStore %18 %37 - %39 = OpLoad %v4uint %gl_LocalInvocationID - %52 = OpCompositeExtract %uint %39 0 - %38 = OpCopyObject %uint %52 + %77 = OpLoad %v3ulong %gl_LocalInvocationID + %52 = OpCompositeExtract %ulong %77 0 + %78 = OpBitcast %ulong %52 + %39 = OpUConvert %uint %78 + %38 = OpCopyObject %uint %39 OpStore %10 %38 %41 = OpLoad %uint %10 - %77 = OpBitcast %uint %41 - %40 = OpUConvert %ulong %77 + %79 = OpBitcast %uint %41 + %40 = OpUConvert %ulong %79 OpStore %11 %40 %42 = OpLoad %ulong %11 %59 = OpCopyObject %ulong %42 %28 = OpSNegate %ulong %59 %44 = OpLoad %_ptr_CrossWorkgroup_uchar %15 - %78 = OpBitcast %_ptr_CrossWorkgroup_uchar %44 - %79 = OpInBoundsPtrAccessChain %_ptr_CrossWorkgroup_uchar %78 %28 - %43 = OpBitcast %_ptr_CrossWorkgroup_uchar %79 + %80 = OpBitcast %_ptr_CrossWorkgroup_uchar %44 + %81 = OpInBoundsPtrAccessChain %_ptr_CrossWorkgroup_uchar %80 %28 + %43 = OpBitcast %_ptr_CrossWorkgroup_uchar %81 OpStore %16 %43 %45 = OpLoad %ulong %11 %60 = OpCopyObject %ulong %45 %29 = OpSNegate %ulong %60 %47 = OpLoad %_ptr_CrossWorkgroup_uchar %18 - %80 = OpBitcast %_ptr_CrossWorkgroup_uchar %47 - %81 = OpInBoundsPtrAccessChain %_ptr_CrossWorkgroup_uchar %80 %29 - %46 = OpBitcast %_ptr_CrossWorkgroup_uchar %81 + %82 = OpBitcast %_ptr_CrossWorkgroup_uchar %47 + %83 = OpInBoundsPtrAccessChain %_ptr_CrossWorkgroup_uchar %82 %29 + %46 = OpBitcast %_ptr_CrossWorkgroup_uchar %83 OpStore %19 %46 %49 = OpLoad %_ptr_CrossWorkgroup_uchar %16 %61 = OpBitcast %_ptr_CrossWorkgroup_ulong %49 - %83 = OpBitcast %_ptr_CrossWorkgroup_uchar %61 - %84 = OpInBoundsPtrAccessChain %_ptr_CrossWorkgroup_uchar %83 %ulong_0 - %54 = OpBitcast %_ptr_CrossWorkgroup_ulong %84 + %85 = OpBitcast %_ptr_CrossWorkgroup_uchar %61 + %86 = OpInBoundsPtrAccessChain %_ptr_CrossWorkgroup_uchar %85 %ulong_0 + %54 = OpBitcast %_ptr_CrossWorkgroup_ulong %86 %48 = OpLoad %ulong %54 OpStore %12 %48 %50 = OpLoad %_ptr_CrossWorkgroup_uchar %19 %51 = OpLoad %ulong %12 %62 = OpBitcast %_ptr_CrossWorkgroup_ulong %50 - %85 = OpBitcast %_ptr_CrossWorkgroup_uchar %62 - %86 = OpInBoundsPtrAccessChain %_ptr_CrossWorkgroup_uchar %85 %ulong_0_0 - %56 = OpBitcast %_ptr_CrossWorkgroup_ulong %86 + %87 = OpBitcast %_ptr_CrossWorkgroup_uchar %62 + %88 = OpInBoundsPtrAccessChain %_ptr_CrossWorkgroup_uchar %87 %ulong_0_0 + %56 = OpBitcast %_ptr_CrossWorkgroup_ulong %88 OpStore %56 %51 OpReturn OpFunctionEnd diff --git a/ptx/src/translate.rs b/ptx/src/translate.rs index d371293..7f1695e 100644 --- a/ptx/src/translate.rs +++ b/ptx/src/translate.rs @@ -1316,13 +1316,13 @@ fn to_ssa<'input, 'b>( convert_to_typed_statements(unadorned_statements, &fn_defs, &mut numeric_id_defs)?; let typed_statements = convert_to_stateful_memory_access(&mut spirv_decl, typed_statements, &mut numeric_id_defs)?; - let typed_statements = fix_builtins(typed_statements, &mut numeric_id_defs)?; let ssa_statements = insert_mem_ssa_statements( typed_statements, &mut numeric_id_defs, &f_args, &mut spirv_decl, )?; + let ssa_statements = fix_builtins(ssa_statements, &mut numeric_id_defs)?; let mut numeric_id_defs = numeric_id_defs.finish(); let expanded_statements = expand_arguments(ssa_statements, &mut numeric_id_defs)?; let expanded_statements = @@ -1345,11 +1345,57 @@ fn fix_builtins( numeric_id_defs: &mut NumericIdResolver, ) -> Result, TranslateError> { let mut result = Vec::with_capacity(typed_statements.len()); - let mut visitor = FixBuiltinsVisitor {}; for s in typed_statements { match s { - Statement::Instruction(inst) => { - result.push(Statement::Instruction(inst.map(&mut visitor)?)) + Statement::LoadVar( + mut + details + @ + LoadVarDetails { + member_index: Some((_, Some(_))), + .. + }, + ) => { + let index = details.member_index.unwrap().0; + if index == 3 { + result.push(Statement::Constant(ConstantDefinition { + dst: details.arg.dst, + typ: ast::ScalarType::U32, + value: ast::ImmediateValue::U64(0), + })); + } else { + let src_type = match numeric_id_defs.special_registers.get(details.arg.src) { + Some(reg) => get_sreg_id_scalar_type(numeric_id_defs, reg), + None => None, + }; + let (sreg_src, scalar_typ, vector_width) = match src_type { + Some(x) => x, + None => { + result.push(Statement::LoadVar(details)); + continue; + } + }; + let temp_id = numeric_id_defs.new_non_variable(Some(details.typ.clone())); + let real_dst = details.arg.dst; + details.arg.dst = temp_id; + result.push(Statement::LoadVar(LoadVarDetails { + arg: Arg2 { + src: sreg_src, + dst: temp_id, + }, + typ: ast::Type::Scalar(scalar_typ), + member_index: Some((index, Some(vector_width))), + })); + result.push(Statement::Conversion(ImplicitConversion { + src: temp_id, + dst: real_dst, + from: ast::Type::Scalar(scalar_typ), + to: ast::Type::Scalar(ast::ScalarType::U32), + kind: ConversionKind::Default, + src_sema: ArgumentSemantics::Default, + dst_sema: ArgumentSemantics::Default, + })); + } } s => result.push(s), } @@ -1357,55 +1403,21 @@ fn fix_builtins( Ok(result) } -struct FixBuiltinsVisitor {} - -impl ArgumentMapVisitor for FixBuiltinsVisitor { - fn id( - &mut self, - desc: ArgumentDescriptor, - typ: Option<&ast::Type>, - ) -> Result { - todo!() - } - - fn operand( - &mut self, - desc: ArgumentDescriptor>, - typ: &ast::Type, - ) -> Result, TranslateError> { - todo!() - } - - fn id_or_vector( - &mut self, - desc: ArgumentDescriptor>, - typ: &ast::Type, - ) -> Result, TranslateError> { - todo!() - } - - fn operand_or_vector( - &mut self, - desc: ArgumentDescriptor>, - typ: &ast::Type, - ) -> Result, TranslateError> { - todo!() - } - - fn src_call_operand( - &mut self, - desc: ArgumentDescriptor>, - typ: &ast::Type, - ) -> Result, TranslateError> { - todo!() - } - - fn src_member_operand( - &mut self, - desc: ArgumentDescriptor<(spirv::Word, u8)>, - typ: (ast::ScalarType, u8), - ) -> Result<(spirv::Word, u8), TranslateError> { - todo!() +fn get_sreg_id_scalar_type( + numeric_id_defs: &mut NumericIdResolver, + sreg: PtxSpecialRegister, +) -> Option<(spirv::Word, ast::ScalarType, u8)> { + match sreg.normalized_sreg_and_type() { + Some((normalized_sreg, typ, vec_width)) => Some(( + numeric_id_defs.special_registers.replace( + numeric_id_defs.current_id, + sreg, + normalized_sreg, + ), + typ, + vec_width, + )), + None => None, } } @@ -2124,7 +2136,7 @@ impl<'a, 'input> InsertMemSSAVisitor<'a, 'input> { }; Some(( idx, - if self.id_def.special_registers.contains_key(&symbol) { + if self.id_def.special_registers.get(symbol).is_some() { Some(vector_width) } else { None @@ -4711,44 +4723,21 @@ impl PtxSpecialRegister { } } - fn push_conversion( - self, - id_def: &mut NumericIdResolver, - func: &mut Vec, - mut composite_read: CompositeRead, - ) { - todo!() - /* + fn normalized_sreg_and_type(self) -> Option<(PtxSpecialRegister, ast::ScalarType, u8)> { match self { - PtxSpecialRegister::Tid - | PtxSpecialRegister::Ntid - | PtxSpecialRegister::Ctaid - | PtxSpecialRegister::Nctaid => { - if composite_read.src_index == 3 { - func.push(Statement::Constant(ConstantDefinition { - dst: composite_read.dst, - typ: ast::ScalarType::U32, - value: ast::ImmediateValue::U64(0), - })); - } else { - let dst = composite_read.dst; - let temp_dst = - id_def.new_non_variable(Some(ast::Type::Scalar(ast::ScalarType::U64))); - composite_read.dst = temp_dst; - func.push(Statement::Composite(composite_read)); - func.push(Statement::Conversion(ImplicitConversion { - src: temp_dst, - dst: dst, - from: ast::Type::Scalar(ast::ScalarType::U64), - to: ast::Type::Scalar(ast::ScalarType::U32), - kind: ConversionKind::Default, - src_sema: ArgumentSemantics::Default, - dst_sema: ArgumentSemantics::Default, - })); - } + PtxSpecialRegister::Tid => Some((PtxSpecialRegister::Tid64, ast::ScalarType::U64, 3)), + PtxSpecialRegister::Ntid => Some((PtxSpecialRegister::Ntid64, ast::ScalarType::U64, 3)), + PtxSpecialRegister::Ctaid => { + Some((PtxSpecialRegister::Ctaid64, ast::ScalarType::U64, 3)) } + PtxSpecialRegister::Nctaid => { + Some((PtxSpecialRegister::Nctaid64, ast::ScalarType::U64, 3)) + } + PtxSpecialRegister::Tid64 + | PtxSpecialRegister::Ntid64 + | PtxSpecialRegister::Ctaid64 + | PtxSpecialRegister::Nctaid64 => None, } - */ } } @@ -4790,7 +4779,27 @@ impl SpecialRegistersMap { } } - fn replace(&mut self) {} + fn replace( + &mut self, + current_id: &mut spirv::Word, + old: PtxSpecialRegister, + new: PtxSpecialRegister, + ) -> spirv::Word { + match self.reg_to_id.entry(old) { + hash_map::Entry::Occupied(e) => { + let id = e.remove(); + self.reg_to_id.insert(new, id); + id + } + hash_map::Entry::Vacant(e) => { + let numeric_id = *current_id; + *current_id += 1; + e.insert(numeric_id); + self.id_to_reg.insert(numeric_id, new); + numeric_id + } + } + } } struct GlobalStringIdResolver<'input> {