Browse Source

* The "Val" intrinsic is now simplified for string constants akin to a
pure function.

J. Gareth "Curious Kit" Moreton 1 year ago
parent
commit
6597f02ebc
2 changed files with 68 additions and 2 deletions
  1. 66 0
      compiler/ncal.pas
  2. 2 2
      compiler/ninl.pas

+ 66 - 0
compiler/ncal.pas

@@ -2734,6 +2734,9 @@ implementation
         maxlennode, outnode, valnode: TNode;
         maxlennode, outnode, valnode: TNode;
         MaxStrLen: Int64;
         MaxStrLen: Int64;
         StringLiteral: string;
         StringLiteral: string;
+        ValOutput: TConstExprInt;
+        ValCode: TCGInt;
+        NewStatements: TStatementNode;
       begin
       begin
         result := nil;
         result := nil;
         case intrinsiccode of
         case intrinsiccode of
@@ -2802,6 +2805,69 @@ implementation
                     end;
                     end;
                 end;
                 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
           else
             ;
             ;
         end;
         end;

+ 2 - 2
compiler/ninl.pas

@@ -1765,9 +1765,9 @@ implementation
         if (destpara.resultdef.typ=enumdef) or
         if (destpara.resultdef.typ=enumdef) or
            ((destpara.resultdef.typ=floatdef) and (tfloatdef(destpara.resultdef).floattype=s64comp))
            ((destpara.resultdef.typ=floatdef) and (tfloatdef(destpara.resultdef).floattype=s64comp))
           then
           then
-            tc:=ccallnode.createintern(procname,newparas)
+            tc:=ccallnode.createfromintrinsic(in_val_x,procname,newparas)
         else
         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(
         addstatement(newstatement,cassignmentnode.create(
           destpara.left,ctypeconvnode.create_internal(tc,destpara.left.resultdef)));
           destpara.left,ctypeconvnode.create_internal(tc,destpara.left.resultdef)));