internal override void GenerateMethodBody(TypeCompilationState compilationState, DiagnosticBag diagnostics) { SyntheticBoundNodeFactory F = new SyntheticBoundNodeFactory(this, this.GetNonNullSyntaxNode(), compilationState, diagnostics); F.CurrentFunction = this; try { LocalSymbol i = F.SynthesizedLocal(F.SpecialType(SpecialType.System_Int32)); LocalSymbol hashCode = F.SynthesizedLocal(F.SpecialType(SpecialType.System_UInt32)); LabelSymbol again = F.GenerateLabel("again"); LabelSymbol start = F.GenerateLabel("start"); ParameterSymbol text = this.Parameters[0]; // This method should be kept consistent with ComputeStringHash //uint hashCode = 0; //if (text != null) //{ // hashCode = unchecked((uint)2166136261); // int i = 0; // goto start; //again: // hashCode = (text[i] ^ hashCode) * 16777619; // i = i + 1; //start: // if (i < text.Length) // goto again; //} //return hashCode; var body = F.Block( ImmutableArray.Create <LocalSymbol>(hashCode, i), F.If( F.Binary(BinaryOperatorKind.ObjectNotEqual, F.SpecialType(SpecialType.System_Boolean), F.Parameter(text), F.Null(text.Type)), F.Block( F.Assignment(F.Local(hashCode), F.Literal((uint)2166136261)), F.Assignment(F.Local(i), F.Literal(0)), F.Goto(start), F.Label(again), F.Assignment( F.Local(hashCode), F.Binary(BinaryOperatorKind.Multiplication, hashCode.Type, F.Binary(BinaryOperatorKind.Xor, hashCode.Type, F.Convert(hashCode.Type, F.Call( F.Parameter(text), F.SpecialMethod(SpecialMember.System_String__Chars), F.Local(i)), Conversion.ImplicitNumeric), F.Local(hashCode)), F.Literal(16777619))), F.Assignment( F.Local(i), F.Binary(BinaryOperatorKind.Addition, i.Type, F.Local(i), F.Literal(1))), F.Label(start), F.If( F.Binary(BinaryOperatorKind.LessThan, F.SpecialType(SpecialType.System_Boolean), F.Local(i), F.Call(F.Parameter(text), F.SpecialMethod(SpecialMember.System_String__Length))), F.Goto(again)))), F.Return(F.Local(hashCode)) ); // NOTE: we created this block in its most-lowered form, so analysis is unnecessary F.CloseMethod(body); } catch (SyntheticBoundNodeFactory.MissingPredefinedMember ex) { diagnostics.Add(ex.Diagnostic); F.CloseMethod(F.ThrowNull()); } }
/// <remarks> /// This method should be kept consistent with <see cref="SynthesizedStringSwitchHashMethod.ComputeStringHash"/> /// </remarks> internal override void GenerateMethodBody(TypeCompilationState compilationState, BindingDiagnosticBag diagnostics) { SyntheticBoundNodeFactory F = new SyntheticBoundNodeFactory(this, this.GetNonNullSyntaxNode(), compilationState, diagnostics); F.CurrentFunction = this; try { ParameterSymbol text = this.Parameters[0]; NamedTypeSymbol spanChar = F.WellKnownType(_isReadOnlySpan ? WellKnownType.System_ReadOnlySpan_T : WellKnownType.System_Span_T) .Construct(F.SpecialType(SpecialType.System_Char)); LocalSymbol i = F.SynthesizedLocal(F.SpecialType(SpecialType.System_Int32)); LocalSymbol hashCode = F.SynthesizedLocal(F.SpecialType(SpecialType.System_UInt32)); LabelSymbol again = F.GenerateLabel("again"); LabelSymbol start = F.GenerateLabel("start"); // uint hashCode = unchecked((uint)2166136261); // int i = 0; // goto start; //again: // hashCode = (text[i] ^ hashCode) * 16777619; // i = i + 1; //start: // if (i < text.Length) // goto again; // return hashCode; var body = F.Block( ImmutableArray.Create <LocalSymbol>(hashCode, i), F.Assignment(F.Local(hashCode), F.Literal((uint)2166136261)), F.Assignment(F.Local(i), F.Literal(0)), F.Goto(start), F.Label(again), F.Assignment( F.Local(hashCode), F.Binary(BinaryOperatorKind.Multiplication, hashCode.Type, F.Binary(BinaryOperatorKind.Xor, hashCode.Type, F.Convert(hashCode.Type, F.Call( F.Parameter(text), F.WellKnownMethod(_isReadOnlySpan ? WellKnownMember.System_ReadOnlySpan_T__get_Item : WellKnownMember.System_Span_T__get_Item).AsMember(spanChar), F.Local(i)), Conversion.ImplicitNumeric), F.Local(hashCode)), F.Literal(16777619))), F.Assignment( F.Local(i), F.Binary(BinaryOperatorKind.Addition, i.Type, F.Local(i), F.Literal(1))), F.Label(start), F.If( F.Binary(BinaryOperatorKind.LessThan, F.SpecialType(SpecialType.System_Boolean), F.Local(i), F.Call( F.Parameter(text), F.WellKnownMethod(_isReadOnlySpan ? WellKnownMember.System_ReadOnlySpan_T__get_Length : WellKnownMember.System_Span_T__get_Length).AsMember(spanChar))), F.Goto(again)), F.Return(F.Local(hashCode)) ); // NOTE: we created this block in its most-lowered form, so analysis is unnecessary F.CloseMethod(body); } catch (SyntheticBoundNodeFactory.MissingPredefinedMember ex) { diagnostics.Add(ex.Diagnostic); F.CloseMethod(F.ThrowNull()); } }