diff --git a/compiler/ncal.pas b/compiler/ncal.pas index 5aece63598..e62e9f6198 100644 --- a/compiler/ncal.pas +++ b/compiler/ncal.pas @@ -2734,6 +2734,9 @@ implementation maxlennode, outnode, valnode: TNode; MaxStrLen: Int64; StringLiteral: string; + ValOutput: TConstExprInt; + ValCode: TCGInt; + NewStatements: TStatementNode; begin result := nil; case intrinsiccode of @@ -2802,6 +2805,69 @@ implementation end; end; end; + in_val_x: + begin + { rare optimization opportunity which takes some extra time, + so check only at level 3+ } + if not(cs_opt_level3 in current_settings.optimizerswitches) then + exit; + { If the input is a constant, attempt to convert, for example: + "Val('5', Output, Code);" to "Output := 5; Code := 0;" } + + { Format of the internal function fpc_val_sint_*str) is: + fpc_val_sint_*str(SizeInt; *String; out ValSInt): ValSInt; } + + { Remember the parameters are in reverse order - the leftmost one + is the integer data size can usually be ignored. + + For fpc_val_uint_*str variants, the data size is not present as + of FPC 3.2.0 + + Para indices: + * 0 = Code output (present even if omitted in original code) + * 1 = String input + * 2 = Data size + } + para := GetParaFromIndex(0); + if Assigned(para) then + begin + outnode := para.left; + para := GetParaFromIndex(1); + if Assigned(para) then + begin + valnode := para.left; + if is_conststringnode(valnode) then + begin + ValOutput.signed := is_signed(ResultDef); + if ValOutput.signed then + Val(TStringConstNode(valnode).value_str, ValOutput.svalue, ValCode) + else + Val(TStringConstNode(valnode).value_str, ValOutput.uvalue, ValCode); + + { Due to the way the node tree works, we have to insert + the assignment to the Code output within the + assignment to the value output (function result), + so use a block node for that} + + Result := internalstatements(NewStatements); + + { Create a node for writing the Code output } + addstatement( + NewStatements, + CAssignmentNode.Create_Internal( + outnode.getcopy(), { The original will get destroyed } + COrdConstNode.Create(ValCode, outnode.ResultDef, False) + ) + ); + + { Now actually create the function result } + valnode := COrdConstNode.Create(ValOutput, ResultDef, False); + addstatement(NewStatements, valnode); + { Result will now undergo firstpass } + end; + end; + end; + end; else ; end; diff --git a/compiler/ninl.pas b/compiler/ninl.pas index 70687b9b4f..27330c5cdb 100644 --- a/compiler/ninl.pas +++ b/compiler/ninl.pas @@ -1765,9 +1765,9 @@ implementation if (destpara.resultdef.typ=enumdef) or ((destpara.resultdef.typ=floatdef) and (tfloatdef(destpara.resultdef).floattype=s64comp)) then - tc:=ccallnode.createintern(procname,newparas) + tc:=ccallnode.createfromintrinsic(in_val_x,procname,newparas) else - tc:=ctypeconvnode.create(ccallnode.createintern(procname,newparas),destpara.left.resultdef); + tc:=ctypeconvnode.create(ccallnode.createfromintrinsic(in_val_x,procname,newparas),destpara.left.resultdef); addstatement(newstatement,cassignmentnode.create( destpara.left,ctypeconvnode.create_internal(tc,destpara.left.resultdef)));