[PATCH] D97606: [Clang interpreter] Avoid storing pointers at unaligned locations

2021-03-03 Thread Nandor Licker via Phabricator via cfe-commits
nand added a comment.

The patches implementing more features/control flow constructs have not yet 
been committed, so if the pre-existing test passes, the functionality should be 
fine. Adjustments can be made later on when those patches are rebased.




Comment at: clang/lib/AST/Interp/Program.h:51
+  /// Returns the value of a marshalled native pointer.
+  const void *getNativePointer(unsigned Idx);
+

This works for now, but in the future we might want to have a unique integer - 
pointer mapping for all types that need to be stored in the bytecode.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D97606/new/

https://reviews.llvm.org/D97606

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D64146: [Clang Interpreter] Initial patch for the constexpr interpreter

2021-02-17 Thread Nandor Licker via Phabricator via cfe-commits
nand added a comment.

CodePtr points into the bytecode emitted by the byte code compiler. In some 
instances, pointers to auxiliary data structures are embedded into the byte 
code, such as functions or AST nodes which contain information relevant to the 
execution of the instruction.

Would it help if instead of encoding pointers, the byte code encoded some 
integers mapped to the original objects?


Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64146/new/

https://reviews.llvm.org/D64146

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D70073: [ConstExprPreter] Implemented function calls and if statements

2020-05-04 Thread Nandor Licker via Phabricator via cfe-commits
nand added a comment.

ping


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D70073/new/

https://reviews.llvm.org/D70073



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D70073: [ConstExprPreter] Implemented function calls and if statements

2020-04-22 Thread Nandor Licker via Phabricator via cfe-commits
nand added a comment.

ping


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D70073/new/

https://reviews.llvm.org/D70073



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D75726: [ConstExprPreter] Updated constant interpreter documentation

2020-04-15 Thread Nandor Licker via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGb3387d1c30ae: [ConstExprPreter] Updated constant interpreter 
documentation (authored by nand).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D75726/new/

https://reviews.llvm.org/D75726

Files:
  clang/docs/ConstantInterpreter.rst

Index: clang/docs/ConstantInterpreter.rst
===
--- clang/docs/ConstantInterpreter.rst
+++ clang/docs/ConstantInterpreter.rst
@@ -8,129 +8,256 @@
 Introduction
 
 
-The constexpr interpreter aims to replace the existing tree evaluator in clang, improving performance on constructs which are executed inefficiently by the evaluator. The interpreter is activated using the following flags:
+The constexpr interpreter aims to replace the existing tree evaluator in
+clang, improving performance on constructs which are executed inefficiently
+by the evaluator. The interpreter is activated using the following flags:
 
-* ``-fexperimental-new-constant-interpreter`` enables the interpreter, emitting an error if an unsupported feature is encountered
+* ``-fexperimental-new-constant-interpreter`` enables the interpreter,
+emitting an error if an unsupported feature is encountered
 
 Bytecode Compilation
 
 
-Bytecode compilation is handled in ``ByteCodeStmtGen.h`` for statements and ``ByteCodeExprGen.h`` for expressions. The compiler has two different backends: one to generate bytecode for functions (``ByteCodeEmitter``) and one to directly evaluate expressions as they are compiled, without generating bytecode (``EvalEmitter``). All functions are compiled to bytecode, while toplevel expressions used in constant contexts are directly evaluated since the bytecode would never be reused. This mechanism aims to pave the way towards replacing the evaluator, improving its performance on functions and loops, while being just as fast on single-use toplevel expressions.
-
-The interpreter relies on stack-based, strongly-typed opcodes. The glue logic between the code generator, along with the enumeration and description of opcodes, can be found in ``Opcodes.td``. The opcodes are implemented as generic template methods in ``Interp.h`` and instantiated with the relevant primitive types by the interpreter loop or by the evaluating emitter.
+Bytecode compilation is handled in ``ByteCodeStmtGen.h`` for statements
+and ``ByteCodeExprGen.h`` for expressions. The compiler has two different
+backends: one to generate bytecode for functions (``ByteCodeEmitter``) and
+one to directly evaluate expressions as they are compiled, without
+generating bytecode (``EvalEmitter``). All functions are compiled to
+bytecode, while toplevel expressions used in constant contexts are directly
+evaluated since the bytecode would never be reused. This mechanism aims to
+pave the way towards replacing the evaluator, improving its performance on
+functions and loops, while being just as fast on single-use toplevel
+expressions.
+
+The interpreter relies on stack-based, strongly-typed opcodes. The glue
+logic between the code generator, along with the enumeration and
+description of opcodes, can be found in ``Opcodes.td``. The opcodes are
+implemented as generic template methods in ``Interp.h`` and instantiated
+with the relevant primitive types by the interpreter loop or by the
+evaluating emitter.
 
 Primitive Types
 ---
 
 * ``PT_{U|S}int{8|16|32|64}``
 
-  Signed or unsigned integers of a specific bit width, implemented using the ```Integral``` type.
+  Signed or unsigned integers of a specific bit width, implemented using
+  the ```Integral``` type.
 
 * ``PT_{U|S}intFP``
 
-  Signed or unsigned integers of an arbitrary, but fixed width used to implement
-  integral types which are required by the target, but are not supported by the host.
-  Under the hood, they rely on APValue. The ``Integral`` specialisation for these
-  types is required by opcodes to share an implementation with fixed integrals.
+  Signed or unsigned integers of an arbitrary, but fixed width used to
+  implement integral types which are required by the target, but are not
+  supported by the host. Under the hood, they rely on APValue. The
+  ``Integral`` specialisation for these types is required by opcodes to
+  share an implementation with fixed integrals.
 
 * ``PT_Bool``
 
-  Representation for boolean types, essentially a 1-bit unsigned ``Integral``.
+  Representation for boolean types, essentially a 1-bit unsigned
+  ``Integral``.
 
 * ``PT_RealFP``
 
-  Arbitrary, but fixed precision floating point numbers. Could be specialised in
-  the future similarly to integers in order to improve floating point performance.
+  Arbitrary, but fixed precision floating point numbers. Could be
+  specialised in the future similarly to integers in order to improve
+  floating point performance.
 
 * ``PT_Ptr``
 
-  Pointer 

[PATCH] D75726: [ConstExprPreter] Updated constant interpreter documentation

2020-04-15 Thread Nandor Licker via Phabricator via cfe-commits
nand updated this revision to Diff 257637.
nand marked 2 inline comments as done.
nand added a comment.

fixed typos


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D75726/new/

https://reviews.llvm.org/D75726

Files:
  clang/docs/ConstantInterpreter.rst

Index: clang/docs/ConstantInterpreter.rst
===
--- clang/docs/ConstantInterpreter.rst
+++ clang/docs/ConstantInterpreter.rst
@@ -8,129 +8,256 @@
 Introduction
 
 
-The constexpr interpreter aims to replace the existing tree evaluator in clang, improving performance on constructs which are executed inefficiently by the evaluator. The interpreter is activated using the following flags:
+The constexpr interpreter aims to replace the existing tree evaluator in
+clang, improving performance on constructs which are executed inefficiently
+by the evaluator. The interpreter is activated using the following flags:
 
-* ``-fexperimental-new-constant-interpreter`` enables the interpreter, emitting an error if an unsupported feature is encountered
+* ``-fexperimental-new-constant-interpreter`` enables the interpreter,
+emitting an error if an unsupported feature is encountered
 
 Bytecode Compilation
 
 
-Bytecode compilation is handled in ``ByteCodeStmtGen.h`` for statements and ``ByteCodeExprGen.h`` for expressions. The compiler has two different backends: one to generate bytecode for functions (``ByteCodeEmitter``) and one to directly evaluate expressions as they are compiled, without generating bytecode (``EvalEmitter``). All functions are compiled to bytecode, while toplevel expressions used in constant contexts are directly evaluated since the bytecode would never be reused. This mechanism aims to pave the way towards replacing the evaluator, improving its performance on functions and loops, while being just as fast on single-use toplevel expressions.
-
-The interpreter relies on stack-based, strongly-typed opcodes. The glue logic between the code generator, along with the enumeration and description of opcodes, can be found in ``Opcodes.td``. The opcodes are implemented as generic template methods in ``Interp.h`` and instantiated with the relevant primitive types by the interpreter loop or by the evaluating emitter.
+Bytecode compilation is handled in ``ByteCodeStmtGen.h`` for statements
+and ``ByteCodeExprGen.h`` for expressions. The compiler has two different
+backends: one to generate bytecode for functions (``ByteCodeEmitter``) and
+one to directly evaluate expressions as they are compiled, without
+generating bytecode (``EvalEmitter``). All functions are compiled to
+bytecode, while toplevel expressions used in constant contexts are directly
+evaluated since the bytecode would never be reused. This mechanism aims to
+pave the way towards replacing the evaluator, improving its performance on
+functions and loops, while being just as fast on single-use toplevel
+expressions.
+
+The interpreter relies on stack-based, strongly-typed opcodes. The glue
+logic between the code generator, along with the enumeration and
+description of opcodes, can be found in ``Opcodes.td``. The opcodes are
+implemented as generic template methods in ``Interp.h`` and instantiated
+with the relevant primitive types by the interpreter loop or by the
+evaluating emitter.
 
 Primitive Types
 ---
 
 * ``PT_{U|S}int{8|16|32|64}``
 
-  Signed or unsigned integers of a specific bit width, implemented using the ```Integral``` type.
+  Signed or unsigned integers of a specific bit width, implemented using
+  the ```Integral``` type.
 
 * ``PT_{U|S}intFP``
 
-  Signed or unsigned integers of an arbitrary, but fixed width used to implement
-  integral types which are required by the target, but are not supported by the host.
-  Under the hood, they rely on APValue. The ``Integral`` specialisation for these
-  types is required by opcodes to share an implementation with fixed integrals.
+  Signed or unsigned integers of an arbitrary, but fixed width used to
+  implement integral types which are required by the target, but are not
+  supported by the host. Under the hood, they rely on APValue. The
+  ``Integral`` specialisation for these types is required by opcodes to
+  share an implementation with fixed integrals.
 
 * ``PT_Bool``
 
-  Representation for boolean types, essentially a 1-bit unsigned ``Integral``.
+  Representation for boolean types, essentially a 1-bit unsigned
+  ``Integral``.
 
 * ``PT_RealFP``
 
-  Arbitrary, but fixed precision floating point numbers. Could be specialised in
-  the future similarly to integers in order to improve floating point performance.
+  Arbitrary, but fixed precision floating point numbers. Could be
+  specialised in the future similarly to integers in order to improve
+  floating point performance.
 
 * ``PT_Ptr``
 
-  Pointer type, defined in ``"Pointer.h"``.
+  Pointer type, defined in ``"Pointe

[PATCH] D75726: [ConstExprPreter] Updated constant interpreter documentation

2020-04-09 Thread Nandor Licker via Phabricator via cfe-commits
nand added a comment.

Thanks for the comments! I tried to clarify what could be done in the future 
and what is already supported.




Comment at: clang/docs/ConstantInterpreter.rst:174
 
   A block containing a primitive reserved storage only for the primitive.
 

rsmith wrote:
> rsmith wrote:
> > reserved -> reserves
> > 
> > How do you distinguish between initialized and 
> > in-lifetime-but-uninitialized primitives? Eg:
> > 
> > ```
> > constexpr int f() {
> >   int a;
> >   return a; // error, a is in-lifetime but uninitialized
> > }
> > ```
> How do you represent the result of casting a pointer to an integer (which we 
> permit only when constant-folding, but nonetheless we do permit)?
Lifetime is handled by invalidating pointers, whereas descriptors and inline 
descriptors keep track of initialised bits. 

In this particular case, which is not yet supported since the interpreter 
presently expects all variables to be initialised, the byte code generator will 
have to emit an opcode that fetches the local and checks the initialised bit. 
Since currently all locals are assumed to be initialised, the opcode for 
fetching a local does not perform this check. For primitives, this bit will 
probably be part of the block.



Comment at: clang/docs/ConstantInterpreter.rst:174
 
   A block containing a primitive reserved storage only for the primitive.
 

nand wrote:
> rsmith wrote:
> > rsmith wrote:
> > > reserved -> reserves
> > > 
> > > How do you distinguish between initialized and 
> > > in-lifetime-but-uninitialized primitives? Eg:
> > > 
> > > ```
> > > constexpr int f() {
> > >   int a;
> > >   return a; // error, a is in-lifetime but uninitialized
> > > }
> > > ```
> > How do you represent the result of casting a pointer to an integer (which 
> > we permit only when constant-folding, but nonetheless we do permit)?
> Lifetime is handled by invalidating pointers, whereas descriptors and inline 
> descriptors keep track of initialised bits. 
> 
> In this particular case, which is not yet supported since the interpreter 
> presently expects all variables to be initialised, the byte code generator 
> will have to emit an opcode that fetches the local and checks the initialised 
> bit. Since currently all locals are assumed to be initialised, the opcode for 
> fetching a local does not perform this check. For primitives, this bit will 
> probably be part of the block.
This is still on the TODO list.

First of all, there should be a fast path which detects common pointer -> int 
-> pointer conversions and avoids all cast, creating opcodes to emit 
diagnostics.

For the generic case, codegen for pointer-to-int will fail with a note and 
compilation will be re-attempted, classifying pointer-wide integers and 
pointers as a primitive type capable of holding either a pointer or an integer.



Comment at: clang/docs/ConstantInterpreter.rst:182
+  initialised, while a value of ``(InitMap*)-1`` indicates that the object was 
+  fully initialised. when all fields are initialised, the map is deallocated 
+  and replaced with that token.

rsmith wrote:
> when -> When
> 
> The overwhelmingly common case is the set of initialized elements is [0, 1, 
> ..., K) for some K. Have you considered instead storing this value as a union 
> of an `InitMap*` and an integer, using the bottom bit to indicate which case 
> we're in? (We don't need to allocate the map at all except in weird cases 
> where someone makes a hole in the array through a pseudo-destructor or 
> allocates out-of-order with `construct_at` or similar.)
> 
> How do you distinguish between in-lifetime-but-uninitialized elements and 
> out-of-lifetime elements? For example:
> 
> ```
> using T = int;
> constexpr int f(bool b) {
>   int arr[5];
>   arr[3].~T();
>   arr[0] = 1; // ok, uninitialized -> initialized
>   if (!b)
> arr[3] = 1; // error, arr[3] is not in lifetime
>   else
> std::construct_at(arr + 3, 0); // ok, not in lifetime -> in lifetime and 
> initialized
>   return arr[3];
> }
> ```
> 
> Maybe we should use two bits per primitive in the `InitMap` case and store 
> both "initialized" and "in-lifetime"?
This is a great suggestion - I think the initmap could also be a rolling 
counter. 

I was not aware of the case that you have mentioned - destructors do pose a 
problem and another map will be required.



Comment at: clang/docs/ConstantInterpreter.rst:194-195
+Records are laid out identically to arrays of composites: each field and base 
+class is preceded by an inline descriptor. The ``InlineDescriptor`` 
+has the following field:
 

rsmith wrote:
> field -> fields
> 
> From the description below, it looks like `sizeof(InlineDescriptor)` is 
> currently 16. That seems unnecessary: We could easily get this down to 8 
> bytes by bit-packing the offset and the flags. (Restricting ourselves to 2^59 
> bytes for each 

[PATCH] D75726: [ConstExprPreter] Updated constant interpreter documentation

2020-04-09 Thread Nandor Licker via Phabricator via cfe-commits
nand updated this revision to Diff 256346.
nand marked 15 inline comments as done.
nand added a comment.

addressed comments, fixed typos


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D75726/new/

https://reviews.llvm.org/D75726

Files:
  clang/docs/ConstantInterpreter.rst

Index: clang/docs/ConstantInterpreter.rst
===
--- clang/docs/ConstantInterpreter.rst
+++ clang/docs/ConstantInterpreter.rst
@@ -8,129 +8,256 @@
 Introduction
 
 
-The constexpr interpreter aims to replace the existing tree evaluator in clang, improving performance on constructs which are executed inefficiently by the evaluator. The interpreter is activated using the following flags:
+The constexpr interpreter aims to replace the existing tree evaluator in
+clang, improving performance on constructs which are executed inefficiently
+by the evaluator. The interpreter is activated using the following flags:
 
-* ``-fexperimental-new-constant-interpreter`` enables the interpreter, emitting an error if an unsupported feature is encountered
+* ``-fexperimental-new-constant-interpreter`` enables the interpreter,
+emitting an error if an unsupported feature is encountered
 
 Bytecode Compilation
 
 
-Bytecode compilation is handled in ``ByteCodeStmtGen.h`` for statements and ``ByteCodeExprGen.h`` for expressions. The compiler has two different backends: one to generate bytecode for functions (``ByteCodeEmitter``) and one to directly evaluate expressions as they are compiled, without generating bytecode (``EvalEmitter``). All functions are compiled to bytecode, while toplevel expressions used in constant contexts are directly evaluated since the bytecode would never be reused. This mechanism aims to pave the way towards replacing the evaluator, improving its performance on functions and loops, while being just as fast on single-use toplevel expressions.
-
-The interpreter relies on stack-based, strongly-typed opcodes. The glue logic between the code generator, along with the enumeration and description of opcodes, can be found in ``Opcodes.td``. The opcodes are implemented as generic template methods in ``Interp.h`` and instantiated with the relevant primitive types by the interpreter loop or by the evaluating emitter.
+Bytecode compilation is handled in ``ByteCodeStmtGen.h`` for statements
+and ``ByteCodeExprGen.h`` for expressions. The compiler has two different
+backends: one to generate bytecode for functions (``ByteCodeEmitter``) and
+one to directly evaluate expressions as they are compiled, without
+generating bytecode (``EvalEmitter``). All functions are compiled to
+bytecode, while toplevel expressions used in constant contexts are directly
+evaluated since the bytecode would never be reused. This mechanism aims to
+pave the way towards replacing the evaluator, improving its performance on
+functions and loops, while being just as fast on single-use toplevel
+expressions.
+
+The interpreter relies on stack-based, strongly-typed opcodes. The glue
+logic between the code generator, along with the enumeration and
+description of opcodes, can be found in ``Opcodes.td``. The opcodes are
+implemented as generic template methods in ``Interp.h`` and instantiated
+with the relevant primitive types by the interpreter loop or by the
+evaluating emitter.
 
 Primitive Types
 ---
 
 * ``PT_{U|S}int{8|16|32|64}``
 
-  Signed or unsigned integers of a specific bit width, implemented using the ```Integral``` type.
+  Signed or unsigned integers of a specific bit width, implemented using
+  the ```Integral``` type.
 
 * ``PT_{U|S}intFP``
 
-  Signed or unsigned integers of an arbitrary, but fixed width used to implement
-  integral types which are required by the target, but are not supported by the host.
-  Under the hood, they rely on APValue. The ``Integral`` specialisation for these
-  types is required by opcodes to share an implementation with fixed integrals.
+  Signed or unsigned integers of an arbitrary, but fixed width used to
+  implement integral types which are required by the target, but are not
+  supported by the host. Under the hood, they rely on APValue. The
+  ``Integral`` specialisation for these types is required by opcodes to
+  share an implementation with fixed integrals.
 
 * ``PT_Bool``
 
-  Representation for boolean types, essentially a 1-bit unsigned ``Integral``.
+  Representation for boolean types, essentially a 1-bit unsigned
+  ``Integral``.
 
 * ``PT_RealFP``
 
-  Arbitrary, but fixed precision floating point numbers. Could be specialised in
-  the future similarly to integers in order to improve floating point performance.
+  Arbitrary, but fixed precision floating point numbers. Could be
+  specialised in the future similarly to integers in order to improve
+  floating point performance.
 
 * ``PT_Ptr``
 
-  Pointer type, defined in ``"Pointer.h"``.
+  Pointer type,

[PATCH] D70086: [ConstExprPreter] Implemented control flow statements

2020-03-12 Thread Nandor Licker via Phabricator via cfe-commits
nand added a comment.

ping


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D70086/new/

https://reviews.llvm.org/D70086



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D75726: [ConstExprPreter] Updated constant interpreter documentation

2020-03-12 Thread Nandor Licker via Phabricator via cfe-commits
nand updated this revision to Diff 249992.
nand added a comment.

Wrapped to ~80 chars/line


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D75726/new/

https://reviews.llvm.org/D75726

Files:
  clang/docs/ConstantInterpreter.rst

Index: clang/docs/ConstantInterpreter.rst
===
--- clang/docs/ConstantInterpreter.rst
+++ clang/docs/ConstantInterpreter.rst
@@ -8,101 +8,166 @@
 Introduction
 
 
-The constexpr interpreter aims to replace the existing tree evaluator in clang, improving performance on constructs which are executed inefficiently by the evaluator. The interpreter is activated using the following flags:
+The constexpr interpreter aims to replace the existing tree evaluator in 
+clang, improving performance on constructs which are executed inefficiently 
+by the evaluator. The interpreter is activated using the following flags:
 
-* ``-fexperimental-new-constant-interpreter`` enables the interpreter, emitting an error if an unsupported feature is encountered
+* ``-fexperimental-new-constant-interpreter`` enables the interpreter, 
+emitting an error if an unsupported feature is encountered
 
 Bytecode Compilation
 
 
-Bytecode compilation is handled in ``ByteCodeStmtGen.h`` for statements and ``ByteCodeExprGen.h`` for expressions. The compiler has two different backends: one to generate bytecode for functions (``ByteCodeEmitter``) and one to directly evaluate expressions as they are compiled, without generating bytecode (``EvalEmitter``). All functions are compiled to bytecode, while toplevel expressions used in constant contexts are directly evaluated since the bytecode would never be reused. This mechanism aims to pave the way towards replacing the evaluator, improving its performance on functions and loops, while being just as fast on single-use toplevel expressions.
-
-The interpreter relies on stack-based, strongly-typed opcodes. The glue logic between the code generator, along with the enumeration and description of opcodes, can be found in ``Opcodes.td``. The opcodes are implemented as generic template methods in ``Interp.h`` and instantiated with the relevant primitive types by the interpreter loop or by the evaluating emitter.
+Bytecode compilation is handled in ``ByteCodeStmtGen.h`` for statements 
+and ``ByteCodeExprGen.h`` for expressions. The compiler has two different 
+backends: one to generate bytecode for functions (``ByteCodeEmitter``) and 
+one to directly evaluate expressions as they are compiled, without 
+generating bytecode (``EvalEmitter``). All functions are compiled to 
+bytecode, while toplevel expressions used in constant contexts are directly 
+evaluated since the bytecode would never be reused. This mechanism aims to 
+pave the way towards replacing the evaluator, improving its performance on 
+functions and loops, while being just as fast on single-use toplevel 
+expressions.
+
+The interpreter relies on stack-based, strongly-typed opcodes. The glue 
+logic between the code generator, along with the enumeration and 
+description of opcodes, can be found in ``Opcodes.td``. The opcodes are 
+implemented as generic template methods in ``Interp.h`` and instantiated 
+with the relevant primitive types by the interpreter loop or by the 
+evaluating emitter.
 
 Primitive Types
 ---
 
 * ``PT_{U|S}int{8|16|32|64}``
 
-  Signed or unsigned integers of a specific bit width, implemented using the ```Integral``` type.
+  Signed or unsigned integers of a specific bit width, implemented using 
+  the ```Integral``` type.
 
 * ``PT_{U|S}intFP``
 
-  Signed or unsigned integers of an arbitrary, but fixed width used to implement
-  integral types which are required by the target, but are not supported by the host.
-  Under the hood, they rely on APValue. The ``Integral`` specialisation for these
-  types is required by opcodes to share an implementation with fixed integrals.
+  Signed or unsigned integers of an arbitrary, but fixed width used to 
+  implement integral types which are required by the target, but are not 
+  supported by the host. Under the hood, they rely on APValue. The 
+  ``Integral`` specialisation for these types is required by opcodes to 
+  share an implementation with fixed integrals.
 
 * ``PT_Bool``
 
-  Representation for boolean types, essentially a 1-bit unsigned ``Integral``.
+  Representation for boolean types, essentially a 1-bit unsigned 
+  ``Integral``.
 
 * ``PT_RealFP``
 
-  Arbitrary, but fixed precision floating point numbers. Could be specialised in
-  the future similarly to integers in order to improve floating point performance.
+  Arbitrary, but fixed precision floating point numbers. Could be 
+  specialised in the future similarly to integers in order to improve 
+  floating point performance.
 
 * ``PT_Ptr``
 
-  Pointer type, defined in ``"Pointer.h"``.
+  Pointer type, defined in ``"Pointe

[PATCH] D70073: [ConstExprPreter] Implemented function calls and if statements

2020-03-12 Thread Nandor Licker via Phabricator via cfe-commits
nand added a comment.

ping


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D70073/new/

https://reviews.llvm.org/D70073



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D70086: [ConstExprPreter] Implemented control flow statements

2020-03-06 Thread Nandor Licker via Phabricator via cfe-commits
nand updated this revision to Diff 248701.
nand added a comment.

rebase


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D70086/new/

https://reviews.llvm.org/D70086

Files:
  clang/lib/AST/Interp/ByteCodeEmitter.cpp
  clang/lib/AST/Interp/ByteCodeExprGen.cpp
  clang/lib/AST/Interp/ByteCodeExprGen.h
  clang/lib/AST/Interp/ByteCodeStmtGen.cpp
  clang/lib/AST/Interp/ByteCodeStmtGen.h
  clang/lib/AST/Interp/Context.cpp
  clang/lib/AST/Interp/Context.h
  clang/lib/AST/Interp/EvalEmitter.cpp
  clang/lib/AST/Interp/InterpLoop.cpp
  clang/lib/AST/Interp/Opcodes.td
  clang/lib/AST/Interp/Opcodes/Comparison.h

Index: clang/lib/AST/Interp/Opcodes/Comparison.h
===
--- clang/lib/AST/Interp/Opcodes/Comparison.h
+++ clang/lib/AST/Interp/Opcodes/Comparison.h
@@ -148,5 +148,16 @@
   return false;
 }
 
+template 
+bool InRange(InterpState &S, CodePtr OpPC) {
+  using T = typename PrimConv::T;
+  const T &RHS = S.Stk.pop();
+  const T &LHS = S.Stk.pop();
+  const T &Value = S.Stk.pop();
+
+  S.Stk.push(LHS <= Value && Value <= RHS);
+  return true;
+}
+
 #endif
 
Index: clang/lib/AST/Interp/Opcodes.td
===
--- clang/lib/AST/Interp/Opcodes.td
+++ clang/lib/AST/Interp/Opcodes.td
@@ -75,7 +75,11 @@
 }
 
 def FPTypeClass : TypeClass {
-  let Types = IntTypeClass.Types;
+  let Types = [];
+}
+
+def IntFPTypeClass : TypeClass {
+  let Types = !listconcat(IntTypeClass.Types, FPTypeClass.Types);
 }
 
 def AluFPRealFPTypeClass : TypeClass {
@@ -334,6 +338,16 @@
 def GT : ComparisonOpcode;
 def GE : ComparisonOpcode;
 
+//===--===//
+// Range test.
+//===--===//
+
+// [Real, Real, Real] -> [Bool]
+def InRange : Opcode {
+  let Types = [IntFPTypeClass];
+  let HasGroup = 1;
+}
+
 //===--===//
 // Stack management.
 //===--===//
Index: clang/lib/AST/Interp/InterpLoop.cpp
===
--- clang/lib/AST/Interp/InterpLoop.cpp
+++ clang/lib/AST/Interp/InterpLoop.cpp
@@ -108,6 +108,8 @@
 return false;
   if (S.checkingPotentialConstantExpression())
 return false;
+  if (!F->isConstexpr())
+return false;
 
   // Adjust the state.
   S.CallStackDepth++;
Index: clang/lib/AST/Interp/EvalEmitter.cpp
===
--- clang/lib/AST/Interp/EvalEmitter.cpp
+++ clang/lib/AST/Interp/EvalEmitter.cpp
@@ -177,6 +177,8 @@
 return false;
   if (S.checkingPotentialConstantExpression())
 return false;
+  if (!F->isConstexpr())
+return false;
   S.Current = new InterpFrame(S, F, S.Current, OpPC, std::move(This));
   return Interpret(S, Result);
 }
Index: clang/lib/AST/Interp/Context.h
===
--- clang/lib/AST/Interp/Context.h
+++ clang/lib/AST/Interp/Context.h
@@ -70,13 +70,6 @@
   /// Classifies an expression.
   llvm::Optional classify(QualType T);
 
-private:
-  /// Runs a function.
-  bool Run(State &Parent, Function *Func, APValue &Result);
-
-  /// Checks a result fromt the interpreter.
-  bool Check(State &Parent, llvm::Expected &&R);
-
 private:
   /// Current compilation context.
   ASTContext &Ctx;
Index: clang/lib/AST/Interp/Context.cpp
===
--- clang/lib/AST/Interp/Context.cpp
+++ clang/lib/AST/Interp/Context.cpp
@@ -27,6 +27,8 @@
 Context::~Context() {}
 
 bool Context::isPotentialConstantExpr(State &Parent, const FunctionDecl *FD) {
+  // Try to compile the function. This either produces an error message (if this
+  // is the first attempt to compile) or returns a dummy function with no body.
   Function *Func = P->getFunction(FD);
   if (!Func) {
 ByteCodeStmtGen C(*this, *P, Parent);
@@ -40,22 +42,43 @@
 }
   }
 
+  // If function has no body, it is definitely not constexpr.
   if (!Func->isConstexpr())
 return false;
 
-  APValue Dummy;
-  return Run(Parent, Func, Dummy);
+  // Run the function in a dummy context.
+  APValue DummyResult;
+  InterpState State(Parent, *P, Stk, *this);
+  State.Current = new InterpFrame(State, Func, nullptr, {}, {});
+  if (Interpret(State, DummyResult))
+return true;
+  Stk.clear();
+  return false;
 }
 
 bool Context::evaluateAsRValue(State &Parent, const Expr *E, APValue &Result) {
   ByteCodeExprGen C(*this, *P, Parent, Stk, Result);
-  return Check(Parent, C.interpretExpr(E));
+  if (auto Flag = C.interpretExpr(E)) {
+return *Flag;
+  } else {
+handleAllErrors(Flag.takeError(), [&Parent](ByteCodeGenError &Err) {
+  Parent.FFDiag(Err.getLoc(), diag::err_experimental_clang_interp_failed);
+  

[PATCH] D75726: [ConstExprPreter] Updated constant interpreter documentation

2020-03-06 Thread Nandor Licker via Phabricator via cfe-commits
nand created this revision.
nand added reviewers: rsmith, Bigcheese, dexonsmith, jfb.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Updated the documentation to better reflect features implemented on the
constexpr branch at https://github.com/nandor/llvm-project and extended
the TODO list with known missing features


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D75726

Files:
  clang/docs/ConstantInterpreter.rst

Index: clang/docs/ConstantInterpreter.rst
===
--- clang/docs/ConstantInterpreter.rst
+++ clang/docs/ConstantInterpreter.rst
@@ -44,21 +44,28 @@
 
 * ``PT_Ptr``
 
-  Pointer type, defined in ``"Pointer.h"``.
+  Pointer type, defined in ``"Pointer.h"``. A pointer can be either null, reference interpreter-allocated memory (``BlockPointer``) or point to an address which can be derived, but not accessed (``ExternPointer``).
 
 * ``PT_FnPtr``
 
-  Function pointer type, can also be a null function pointer. Defined in ``"Pointer.h"``.
+  Function pointer type, can also be a null function pointer. Defined in ``"FnPointer.h"``.
 
 * ``PT_MemPtr``
 
-  Member pointer type, can also be a null member pointer. Defined in ``"Pointer.h"``
+  Member pointer type, can also be a null member pointer. Defined in ``"MemberPointer.h"``
+
+* ``PT_VoidPtr``
+
+  Void pointer type, can be used for rount-trip casts. Represented as the union of all pointers which can be cast to void. Defined in ``"VoidPointer.h"``.
+
+* ``PT_ObjCBlockPtr``
+
+  Pointer type for ObjC blocks. Defined in ``"ObjCBlockPointer.h"``.
 
 Composite types
 ---
 
-The interpreter distinguishes two kinds of composite types: arrays and records. Unions are represented as records, except a single field can be marked as active. The contents of inactive fields are kept until they
-are reactivated and overwritten.
+The interpreter distinguishes two kinds of composite types: arrays and records (structs and classes). Unions are represented as records, except at most a single field can be marked as active. The contents of inactive fields are kept until they are reactivated and overwritten. Complex numbers (``_Complex``) and vectors (``__attribute((vector_size(16)))``) are treated as arrays.
 
 
 Bytecode Execution
@@ -85,8 +92,6 @@
 
 * ``IsStatic`` indicates whether the block has static duration in the interpreter, i.e. it is not a local in a frame.
 
-* ``IsExtern`` indicates that the block was created for an extern and the storage cannot be read or written.
-
 * ``DeclID`` identifies each global declaration (it is set to an invalid and irrelevant value for locals) in order to prevent illegal writes and reads involving globals and temporaries with static storage duration.
 
 Static blocks are never deallocated, but local ones might be deallocated even when there are live pointers to them. Pointers are only valid as long as the blocks they point to are valid, so a block with pointers to it whose lifetime ends is kept alive until all pointers to it go out of scope. Since the frame is destroyed on function exit, such blocks are turned into a ``DeadBlock`` and copied to storage managed by the interpreter itself, not the frame. Reads and writes to these blocks are illegal and cause an appropriate diagnostic to be emitted. When the last pointer goes out of scope, dead blocks are also deallocated.
@@ -97,7 +102,7 @@
 * **DtorFn**: invokes the destructors of non-trivial objects.
 * **MoveFn**: moves a block to dead storage.
 
-Non-static blocks track all the pointers into them through an intrusive doubly-linked list, this is required in order to adjust all pointers when transforming a block into a dead block.
+Non-static blocks track all the pointers into them through an intrusive doubly-linked list, required to adjust all pointers when transforming a block into a dead block.
 
 Descriptors
 ---
@@ -110,13 +115,13 @@
 
 * **Arrays of primitives**
 
-  An array of primitives contains a pointer to an ``InitMap`` storage as its first field: the initialisation map is a bit map indicating all elements of the array which were initialised. If the pointer is null, no elements were initialised, while a value of ``(InitMap)-1`` indicates that the object was fully initialised. when all fields are initialised, the map is deallocated and replaced with that token.
+  An array of primitives contains a pointer to an ``InitMap`` storage as its first field: the initialisation map is a bit map indicating all elements of the array which were initialised. If the pointer is null, no elements were initialised, while a value of ``(InitMap*)-1`` indicates that the object was fully initialised. when all fields are initialised, the map is deallocated and replaced with that token.
 
   Array elements are stored sequentially, without padding, after the pointer to the map.
 
 * **Arrays of composites and records**
 
-  Each element in an array of composites is preceded

[PATCH] D74934: [Clang interpreter] Rename Block.{h,cpp} to AllocatedBlock.{h,cpp}

2020-02-21 Thread Nandor Licker via Phabricator via cfe-commits
nand added a comment.

Was wondering if ```InterpBlock``` might be a more suitable name?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D74934/new/

https://reviews.llvm.org/D74934



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D70073: [ConstExprPreter] Implemented function calls and if statements

2020-01-03 Thread Nandor Licker via Phabricator via cfe-commits
nand added a comment.

ping


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D70073/new/

https://reviews.llvm.org/D70073



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D70073: [ConstExprPreter] Implemented function calls and if statements

2019-12-20 Thread Nandor Licker via Phabricator via cfe-commits
nand added a comment.

ping


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D70073/new/

https://reviews.llvm.org/D70073



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D70073: [ConstExprPreter] Implemented function calls and if statements

2019-12-13 Thread Nandor Licker via Phabricator via cfe-commits
nand added a comment.

ping


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D70073/new/

https://reviews.llvm.org/D70073



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D70073: [ConstExprPreter] Implemented function calls and if statements

2019-12-06 Thread Nandor Licker via Phabricator via cfe-commits
nand added a comment.

ping


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D70073/new/

https://reviews.llvm.org/D70073



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D70073: [ConstExprPreter] Implemented function calls and if statements

2019-12-02 Thread Nandor Licker via Phabricator via cfe-commits
nand added a comment.

ping


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D70073/new/

https://reviews.llvm.org/D70073



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D70071: [ConstExprPreter] Removed the flag forcing the use of the interpreter

2019-11-27 Thread Nandor Licker via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGf584f04dab69: [ConstExprPreter] Removed the flag forcing the 
use of the interpreter (authored by nand).

Changed prior to commit:
  https://reviews.llvm.org/D70071?vs=230791&id=231310#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D70071/new/

https://reviews.llvm.org/D70071

Files:
  clang/docs/ConstantInterpreter.rst
  clang/include/clang/Basic/LangOptions.def
  clang/include/clang/Driver/Options.td
  clang/lib/AST/ExprConstant.cpp
  clang/lib/AST/Interp/Context.cpp
  clang/lib/AST/Interp/Context.h
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/test/AST/Interp/cond.cpp

Index: clang/test/AST/Interp/cond.cpp
===
--- clang/test/AST/Interp/cond.cpp
+++ clang/test/AST/Interp/cond.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++17 -fsyntax-only -fforce-experimental-new-constant-interpreter %s -verify
+// RUN: %clang_cc1 -std=c++17 -fsyntax-only -fexperimental-new-constant-interpreter %s -verify
 // RUN: %clang_cc1 -std=c++17 -fsyntax-only %s -verify
 // expected-no-diagnostics
 
Index: clang/lib/Frontend/CompilerInvocation.cpp
===
--- clang/lib/Frontend/CompilerInvocation.cpp
+++ clang/lib/Frontend/CompilerInvocation.cpp
@@ -2854,8 +2854,6 @@
   getLastArgIntValue(Args, OPT_fconstexpr_steps, 1048576, Diags);
   Opts.EnableNewConstInterp =
   Args.hasArg(OPT_fexperimental_new_constant_interpreter);
-  Opts.ForceNewConstInterp =
-  Args.hasArg(OPT_fforce_experimental_new_constant_interpreter);
   Opts.BracketDepth = getLastArgIntValue(Args, OPT_fbracket_depth, 256, Diags);
   Opts.DelayedTemplateParsing = Args.hasArg(OPT_fdelayed_template_parsing);
   Opts.NumLargeByValueCopy =
Index: clang/lib/Driver/ToolChains/Clang.cpp
===
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -4503,9 +4503,6 @@
   if (Args.hasArg(options::OPT_fexperimental_new_constant_interpreter))
 CmdArgs.push_back("-fexperimental-new-constant-interpreter");
 
-  if (Args.hasArg(options::OPT_fforce_experimental_new_constant_interpreter))
-CmdArgs.push_back("-fforce-experimental-new-constant-interpreter");
-
   if (Arg *A = Args.getLastArg(options::OPT_fbracket_depth_EQ)) {
 CmdArgs.push_back("-fbracket-depth");
 CmdArgs.push_back(A->getValue());
Index: clang/lib/AST/Interp/Context.h
===
--- clang/lib/AST/Interp/Context.h
+++ clang/lib/AST/Interp/Context.h
@@ -34,16 +34,6 @@
 class State;
 enum PrimType : unsigned;
 
-/// Wrapper around interpreter termination results.
-enum class InterpResult {
-  /// Interpreter successfully computed a value.
-  Success,
-  /// Interpreter encountered an error and quit.
-  Fail,
-  /// Interpreter encountered an unimplemented feature, AST fallback.
-  Bail,
-};
-
 /// Holds all information required to evaluate constexpr code in a module.
 class Context {
 public:
@@ -54,15 +44,13 @@
   ~Context();
 
   /// Checks if a function is a potential constant expression.
-  InterpResult isPotentialConstantExpr(State &Parent,
-   const FunctionDecl *FnDecl);
+  bool isPotentialConstantExpr(State &Parent, const FunctionDecl *FnDecl);
 
   /// Evaluates a toplevel expression as an rvalue.
-  InterpResult evaluateAsRValue(State &Parent, const Expr *E, APValue &Result);
+  bool evaluateAsRValue(State &Parent, const Expr *E, APValue &Result);
 
   /// Evaluates a toplevel initializer.
-  InterpResult evaluateAsInitializer(State &Parent, const VarDecl *VD,
- APValue &Result);
+  bool evaluateAsInitializer(State &Parent, const VarDecl *VD, APValue &Result);
 
   /// Returns the AST context.
   ASTContext &getASTContext() const { return Ctx; }
@@ -78,16 +66,14 @@
 
 private:
   /// Runs a function.
-  InterpResult Run(State &Parent, Function *Func, APValue &Result);
+  bool Run(State &Parent, Function *Func, APValue &Result);
 
   /// Checks a result fromt the interpreter.
-  InterpResult Check(State &Parent, llvm::Expected &&R);
+  bool Check(State &Parent, llvm::Expected &&R);
 
 private:
   /// Current compilation context.
   ASTContext &Ctx;
-  /// Flag to indicate if the use of the interpreter is mandatory.
-  bool ForceInterp;
   /// Interpreter stack, shared across invocations.
   InterpStack Stk;
   /// Constexpr program.
Index: clang/lib/AST/Interp/Context.cpp
===
--- clang/lib/AST/Interp/Context.cpp
+++ clang/lib/AST/Interp/Context.cpp
@@ -21,44 +21,37 @@
 using namespace clang;
 using namespace clang::interp;
 
-Context::Context(ASTContext &Ctx)
-: Ctx(Ctx), ForceInterp(getLang

[PATCH] D70071: [ConstExprPreter] Removed the flag forcing the use of the interpreter

2019-11-24 Thread Nandor Licker via Phabricator via cfe-commits
nand updated this revision to Diff 230791.
nand added a comment.

rebase


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D70071/new/

https://reviews.llvm.org/D70071

Files:
  clang/docs/ConstantInterpreter.rst
  clang/include/clang/Basic/LangOptions.def
  clang/include/clang/Driver/Options.td
  clang/lib/AST/ExprConstant.cpp
  clang/lib/AST/Interp/Context.cpp
  clang/lib/AST/Interp/Context.h
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/test/AST/Interp/cond.cpp

Index: clang/test/AST/Interp/cond.cpp
===
--- clang/test/AST/Interp/cond.cpp
+++ clang/test/AST/Interp/cond.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++17 -fsyntax-only -fforce-experimental-new-constant-interpreter %s -verify
+// RUN: %clang_cc1 -std=c++17 -fsyntax-only -fexperimental-new-constant-interpreter %s -verify
 // RUN: %clang_cc1 -std=c++17 -fsyntax-only %s -verify
 // expected-no-diagnostics
 
Index: clang/lib/Frontend/CompilerInvocation.cpp
===
--- clang/lib/Frontend/CompilerInvocation.cpp
+++ clang/lib/Frontend/CompilerInvocation.cpp
@@ -2854,8 +2854,6 @@
   getLastArgIntValue(Args, OPT_fconstexpr_steps, 1048576, Diags);
   Opts.EnableNewConstInterp =
   Args.hasArg(OPT_fexperimental_new_constant_interpreter);
-  Opts.ForceNewConstInterp =
-  Args.hasArg(OPT_fforce_experimental_new_constant_interpreter);
   Opts.BracketDepth = getLastArgIntValue(Args, OPT_fbracket_depth, 256, Diags);
   Opts.DelayedTemplateParsing = Args.hasArg(OPT_fdelayed_template_parsing);
   Opts.NumLargeByValueCopy =
Index: clang/lib/Driver/ToolChains/Clang.cpp
===
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -4484,9 +4484,6 @@
   if (Args.hasArg(options::OPT_fexperimental_new_constant_interpreter))
 CmdArgs.push_back("-fexperimental-new-constant-interpreter");
 
-  if (Args.hasArg(options::OPT_fforce_experimental_new_constant_interpreter))
-CmdArgs.push_back("-fforce-experimental-new-constant-interpreter");
-
   if (Arg *A = Args.getLastArg(options::OPT_fbracket_depth_EQ)) {
 CmdArgs.push_back("-fbracket-depth");
 CmdArgs.push_back(A->getValue());
Index: clang/lib/AST/Interp/Context.h
===
--- clang/lib/AST/Interp/Context.h
+++ clang/lib/AST/Interp/Context.h
@@ -34,16 +34,6 @@
 class State;
 enum PrimType : unsigned;
 
-/// Wrapper around interpreter termination results.
-enum class InterpResult {
-  /// Interpreter successfully computed a value.
-  Success,
-  /// Interpreter encountered an error and quit.
-  Fail,
-  /// Interpreter encountered an unimplemented feature, AST fallback.
-  Bail,
-};
-
 /// Holds all information required to evaluate constexpr code in a module.
 class Context {
 public:
@@ -54,15 +44,13 @@
   ~Context();
 
   /// Checks if a function is a potential constant expression.
-  InterpResult isPotentialConstantExpr(State &Parent,
-   const FunctionDecl *FnDecl);
+  bool isPotentialConstantExpr(State &Parent, const FunctionDecl *FnDecl);
 
   /// Evaluates a toplevel expression as an rvalue.
-  InterpResult evaluateAsRValue(State &Parent, const Expr *E, APValue &Result);
+  bool evaluateAsRValue(State &Parent, const Expr *E, APValue &Result);
 
   /// Evaluates a toplevel initializer.
-  InterpResult evaluateAsInitializer(State &Parent, const VarDecl *VD,
- APValue &Result);
+  bool evaluateAsInitializer(State &Parent, const VarDecl *VD, APValue &Result);
 
   /// Returns the AST context.
   ASTContext &getASTContext() const { return Ctx; }
@@ -78,16 +66,14 @@
 
 private:
   /// Runs a function.
-  InterpResult Run(State &Parent, Function *Func, APValue &Result);
+  bool Run(State &Parent, Function *Func, APValue &Result);
 
   /// Checks a result fromt the interpreter.
-  InterpResult Check(State &Parent, llvm::Expected &&R);
+  bool Check(State &Parent, llvm::Expected &&R);
 
 private:
   /// Current compilation context.
   ASTContext &Ctx;
-  /// Flag to indicate if the use of the interpreter is mandatory.
-  bool ForceInterp;
   /// Interpreter stack, shared across invocations.
   InterpStack Stk;
   /// Constexpr program.
Index: clang/lib/AST/Interp/Context.cpp
===
--- clang/lib/AST/Interp/Context.cpp
+++ clang/lib/AST/Interp/Context.cpp
@@ -21,44 +21,37 @@
 using namespace clang;
 using namespace clang::interp;
 
-Context::Context(ASTContext &Ctx)
-: Ctx(Ctx), ForceInterp(getLangOpts().ForceNewConstInterp),
-  P(new Program(*this)) {}
+Context::Context(ASTContext &Ctx) : Ctx(Ctx), P(new Program(*this)) {}
 
 Context::~Context() {}
 
-InterpResult Context::isPotentialConstantExpr(

[PATCH] D70071: [ConstExprPreter] Removed the flag forcing the use of the interpreter

2019-11-22 Thread Nandor Licker via Phabricator via cfe-commits
nand added a comment.

ping


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D70071/new/

https://reviews.llvm.org/D70071



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D70087: [ConstExprPreter] String and basic pointer arithmetic.

2019-11-11 Thread Nandor Licker via Phabricator via cfe-commits
nand created this revision.
nand added reviewers: rsmith, jfb, Bigcheese, dexonsmith.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Implemented string constants and the following pointer operations:

- AddOffset
- SubOffset
- Narrow
- Expand
- LogicalNot

To allow for sensible tests, short-circuiting logical ops were also implemented.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D70087

Files:
  clang/lib/AST/Interp/ByteCodeExprGen.cpp
  clang/lib/AST/Interp/ByteCodeExprGen.h
  clang/lib/AST/Interp/Interp.h
  clang/lib/AST/Interp/Opcodes.td
  clang/lib/AST/Interp/Opcodes/Logical.h
  clang/lib/AST/Interp/Opcodes/Offset.h
  clang/lib/AST/Interp/Program.cpp
  clang/lib/AST/Interp/Program.h
  clang/test/AST/Interp/string.cpp

Index: clang/test/AST/Interp/string.cpp
===
--- /dev/null
+++ clang/test/AST/Interp/string.cpp
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -std=c++17 -fsyntax-only -fexperimental-new-constant-interpreter %s -verify
+// RUN: %clang_cc1 -std=c++17 -fsyntax-only %s -verify
+// expected-no-diagnostics
+
+constexpr bool streq(const char *a, const char *b) {
+  while (*a && *a == *b) {
+a = a + 1;
+b = b + 1;
+  }
+  return *a == *b;
+}
+
+constexpr bool is_equal() {
+  const char *a = "Hello";
+  const char *b = "Hello";
+  return streq(a, b);
+}
+
+static_assert(is_equal());
+
+constexpr bool not_equal() {
+  const char *a = "HA";
+  const char *b = "HB";
+  return streq(a, b);
+}
+
+static_assert(!streq("HA", "HB"));
Index: clang/lib/AST/Interp/Program.h
===
--- clang/lib/AST/Interp/Program.h
+++ clang/lib/AST/Interp/Program.h
@@ -63,6 +63,14 @@
 public:
   Program(Context &Ctx) : Ctx(Ctx) {}
 
+  /// Emits a string literal among global data.
+  unsigned createGlobalString(const StringLiteral *S);
+
+  /// Returns a pointer to a global.
+  Pointer getPtrGlobal(GlobalLocation Idx);
+  /// Returns  a pointer to a global by index.
+  Pointer getPtrGlobal(const ValueDecl *VD);
+
   /// Creates a new function from a code range.
   template 
   Function *createFunction(const FunctionDecl *Def, Ts &&... Args) {
@@ -95,7 +103,11 @@
 
 private:
   friend class DeclScope;
- /// Reference to the VM context.
+
+  llvm::Optional createGlobal(const DeclTy &D, QualType Ty,
+  bool IsStatic, bool IsExtern);
+
+  /// Reference to the VM context.
   Context &Ctx;
   /// Mapping from decls to cached bytecode functions.
   llvm::DenseMap> Funcs;
@@ -108,9 +120,38 @@
   /// Custom allocator for global storage.
   using PoolAllocTy = llvm::BumpPtrAllocatorImpl;
 
+  /// Descriptor + storage for a global object.
+  ///
+  /// Global objects never go out of scope, thus they do not track pointers.
+  class Global {
+  public:
+/// Create a global descriptor for string literals.
+template 
+Global(Tys... Args) : B(std::forward(Args)...) {}
+
+/// Allocates the global in the pool, reserving storate for data.
+void *operator new(size_t Meta, PoolAllocTy &Alloc, size_t Data) {
+  return Alloc.Allocate(Meta + Data, alignof(void *));
+}
+
+/// Return a pointer to the data.
+char *data() { return B.data(); }
+/// Return a pointer to the block.
+Block *block() { return &B; }
+
+  private:
+/// Required metadata - does not actually track pointers.
+Block B;
+  };
+
   /// Allocator for globals.
   PoolAllocTy Allocator;
 
+  /// Global objects.
+  std::vector Globals;
+  /// Cached global indices.
+  llvm::DenseMap GlobalIndices;
+
   /// Creates a new descriptor.
   template  Descriptor *allocateDescriptor(Ts &&... Args) {
 return new (Allocator) Descriptor(std::forward(Args)...);
Index: clang/lib/AST/Interp/Program.cpp
===
--- clang/lib/AST/Interp/Program.cpp
+++ clang/lib/AST/Interp/Program.cpp
@@ -18,6 +18,78 @@
 using namespace clang;
 using namespace clang::interp;
 
+unsigned Program::createGlobalString(const StringLiteral *S) {
+  const size_t CharWidth = S->getCharByteWidth();
+  const size_t BitWidth = CharWidth * Ctx.getCharBit();
+
+  PrimType CharType;
+  switch (CharWidth) {
+  case 1:
+CharType = PT_Sint8;
+break;
+  case 2:
+CharType = PT_Uint16;
+break;
+  case 4:
+CharType = PT_Uint32;
+break;
+  default:
+llvm_unreachable("unsupported character width");
+  }
+
+  // Create a descriptor for the string.
+  Descriptor *Desc = allocateDescriptor(S, CharType, S->getLength() + 1,
+/*isConst=*/true,
+/*isTemporary=*/false,
+/*isMutable=*/false);
+
+  // Allocate storage for the string.
+  // The byte length does not include the null terminator.
+  unsigned I = Globals.size();
+  unsigned Sz = Desc->getAllocSize();
+  auto *G = new (Al

[PATCH] D70086: [ConstExprPreter] Implemented control flow statements

2019-11-11 Thread Nandor Licker via Phabricator via cfe-commits
nand created this revision.
nand added reviewers: Bigcheese, jfb, rsmith, dexonsmith.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Added support for:

- for
- switch
- do-while
- while

Also implemented assignment to enable useful tests.

The patch also includes range-based for loops which are
not yet tested, but having them in ByteCodeStmtGen should
simplify the process of slicing off further patches.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D70086

Files:
  clang/lib/AST/Interp/ByteCodeEmitter.cpp
  clang/lib/AST/Interp/ByteCodeExprGen.cpp
  clang/lib/AST/Interp/ByteCodeExprGen.h
  clang/lib/AST/Interp/ByteCodeStmtGen.cpp
  clang/lib/AST/Interp/ByteCodeStmtGen.h
  clang/lib/AST/Interp/Context.cpp
  clang/lib/AST/Interp/Context.h
  clang/lib/AST/Interp/EvalEmitter.cpp
  clang/lib/AST/Interp/InterpLoop.cpp
  clang/lib/AST/Interp/Opcodes.td
  clang/lib/AST/Interp/Opcodes/Comparison.h
  clang/test/AST/Interp/flow.cpp

Index: clang/test/AST/Interp/flow.cpp
===
--- /dev/null
+++ clang/test/AST/Interp/flow.cpp
@@ -0,0 +1,116 @@
+// RUN: %clang_cc1 -std=c++17 -fsyntax-only -fexperimental-new-constant-interpreter %s -verify
+// RUN: %clang_cc1 -std=c++17 -fsyntax-only %s -verify
+// expected-no-diagnostics
+
+constexpr int fn_for_break(int n) {
+  int x = 0;
+  for (int i = 0; i < 20; i = i + 1) {
+if (i == n)
+  break;
+x = x + 1;
+  }
+  return x;
+}
+using A = int[5];
+using A = int[fn_for_break(5)];
+
+constexpr int fn_for_cont(int n) {
+  int x = 0;
+  for (int i = 0; i < 20; i = i + 1) {
+if (i < n)
+  continue;
+x = x + 1;
+  }
+  return x;
+}
+using B = int[15];
+using B = int[fn_for_cont(5)];
+
+constexpr int fn_while_break(unsigned n) {
+  int x = 0;
+  int i = 0;
+  while (int next = i = i + 1) {
+if (next == n) {
+  break;
+}
+x = x + 1;
+  }
+  return x;
+}
+using C = int[4];
+using C = int[fn_while_break(5)];
+
+constexpr int fn_while_cont(unsigned n) {
+  int x = 0;
+  int i = 0;
+  while (i < 10) {
+i = i + 1;
+if (i < n) {
+  continue;
+}
+x = x + 1;
+  }
+  return x;
+}
+using D = int[6];
+using D = int[fn_while_cont(5)];
+
+constexpr int fn_do_break(unsigned n) {
+  int x = 0;
+  int i = 0;
+  do {
+if (i == n) {
+  break;
+}
+x = x + 1;
+i = i + 1;
+  } while (i < 20);
+  return x;
+}
+using E = int[5];
+using E = int[fn_do_break(5)];
+
+constexpr int fn_do_continue(unsigned n) {
+  int x = 0;
+  int i = 0;
+  do {
+i = i + 1;
+if (i < n) {
+  continue;
+}
+x = x + 1;
+  } while (i < 20);
+  return x;
+}
+using F = int[16];
+using F = int[fn_do_continue(5)];
+
+constexpr int fn_for_cond_var(int n) {
+  int a = 0;
+  for (int i = n; int b = a + 1; i = i + 1) {
+if (i == 50) {
+  a = 0 - b;
+}
+  }
+  return a - 1;
+}
+
+using G = int[-fn_for_cond_var(10)];
+using G = int[2];
+
+constexpr int fn_switch(int a) {
+  switch (a) {
+case 0: return 2;
+case 1: return 5;
+default: return 6;
+  }
+}
+
+using H0 = int[2];
+using H0 = int[fn_switch(0)];
+
+using H1 = int[5];
+using H1 = int[fn_switch(1)];
+
+using H2 = int[6];
+using H2 = int[fn_switch(2)];
Index: clang/lib/AST/Interp/Opcodes/Comparison.h
===
--- clang/lib/AST/Interp/Opcodes/Comparison.h
+++ clang/lib/AST/Interp/Opcodes/Comparison.h
@@ -118,4 +118,15 @@
   return false;
 }
 
+template 
+bool InRange(InterpState &S, CodePtr OpPC) {
+  using T = typename PrimConv::T;
+  const T &RHS = S.Stk.pop();
+  const T &LHS = S.Stk.pop();
+  const T &Value = S.Stk.pop();
+
+  S.Stk.push(LHS <= Value && Value <= RHS);
+  return true;
+}
+
 #endif
Index: clang/lib/AST/Interp/Opcodes.td
===
--- clang/lib/AST/Interp/Opcodes.td
+++ clang/lib/AST/Interp/Opcodes.td
@@ -339,6 +339,16 @@
 def GT : ComparisonOpcode;
 def GE : ComparisonOpcode;
 
+//===--===//
+// Range test.
+//===--===//
+
+// [Real, Real, Real] -> [Bool]
+def InRange : Opcode {
+  let Types = [AluFPTypeClass];
+  let HasGroup = 1;
+}
+
 //===--===//
 // Stack management.
 //===--===//
Index: clang/lib/AST/Interp/InterpLoop.cpp
===
--- clang/lib/AST/Interp/InterpLoop.cpp
+++ clang/lib/AST/Interp/InterpLoop.cpp
@@ -108,6 +108,8 @@
 return false;
   if (S.checkingPotentialConstantExpression())
 return false;
+  if (!F->isConstexpr())
+return false;
 
   // Adjust the state.
   S.CallStackDepth++;
Index: clang/lib/AST/Interp/EvalEmitter.cpp
==

[PATCH] D70071: [ConstExprPreter] Removed the flag forcing the use of the interpreter

2019-11-11 Thread Nandor Licker via Phabricator via cfe-commits
nand created this revision.
nand added reviewers: jfb, Bigcheese, rsmith, dexonsmith.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
nand edited the summary of this revision.

Removed the `-fforce-experimental-new-constant-interpreter flag`, leaving
only the `-fexperimental-new-constant-interpreter` one. The interpreter
now always emits an error on an unsupported feature.

Allowing the interpreter to bail out would require a mapping from APValue to
interpreter memory, which will not be necessary in the final version. It is 
more sensible to always emit an error if the interpreter fails.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D70071

Files:
  clang/docs/ConstantInterpreter.rst
  clang/include/clang/Basic/LangOptions.def
  clang/include/clang/Driver/Options.td
  clang/lib/AST/ExprConstant.cpp
  clang/lib/AST/Interp/Context.cpp
  clang/lib/AST/Interp/Context.h
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/test/AST/Interp/cond.cpp

Index: clang/test/AST/Interp/cond.cpp
===
--- clang/test/AST/Interp/cond.cpp
+++ clang/test/AST/Interp/cond.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++17 -fsyntax-only -fforce-experimental-new-constant-interpreter %s -verify
+// RUN: %clang_cc1 -std=c++17 -fsyntax-only -fexperimental-new-constant-interpreter %s -verify
 // RUN: %clang_cc1 -std=c++17 -fsyntax-only %s -verify
 // expected-no-diagnostics
 
Index: clang/lib/Frontend/CompilerInvocation.cpp
===
--- clang/lib/Frontend/CompilerInvocation.cpp
+++ clang/lib/Frontend/CompilerInvocation.cpp
@@ -2836,8 +2836,6 @@
   getLastArgIntValue(Args, OPT_fconstexpr_steps, 1048576, Diags);
   Opts.EnableNewConstInterp =
   Args.hasArg(OPT_fexperimental_new_constant_interpreter);
-  Opts.ForceNewConstInterp =
-  Args.hasArg(OPT_fforce_experimental_new_constant_interpreter);
   Opts.BracketDepth = getLastArgIntValue(Args, OPT_fbracket_depth, 256, Diags);
   Opts.DelayedTemplateParsing = Args.hasArg(OPT_fdelayed_template_parsing);
   Opts.NumLargeByValueCopy =
Index: clang/lib/Driver/ToolChains/Clang.cpp
===
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -4428,9 +4428,6 @@
   if (Args.hasArg(options::OPT_fexperimental_new_constant_interpreter))
 CmdArgs.push_back("-fexperimental-new-constant-interpreter");
 
-  if (Args.hasArg(options::OPT_fforce_experimental_new_constant_interpreter))
-CmdArgs.push_back("-fforce-experimental-new-constant-interpreter");
-
   if (Arg *A = Args.getLastArg(options::OPT_fbracket_depth_EQ)) {
 CmdArgs.push_back("-fbracket-depth");
 CmdArgs.push_back(A->getValue());
Index: clang/lib/AST/Interp/Context.h
===
--- clang/lib/AST/Interp/Context.h
+++ clang/lib/AST/Interp/Context.h
@@ -34,16 +34,6 @@
 class State;
 enum PrimType : unsigned;
 
-/// Wrapper around interpreter termination results.
-enum class InterpResult {
-  /// Interpreter successfully computed a value.
-  Success,
-  /// Interpreter encountered an error and quit.
-  Fail,
-  /// Interpreter encountered an unimplemented feature, AST fallback.
-  Bail,
-};
-
 /// Holds all information required to evaluate constexpr code in a module.
 class Context {
 public:
@@ -54,15 +44,13 @@
   ~Context();
 
   /// Checks if a function is a potential constant expression.
-  InterpResult isPotentialConstantExpr(State &Parent,
-   const FunctionDecl *FnDecl);
+  bool isPotentialConstantExpr(State &Parent, const FunctionDecl *FnDecl);
 
   /// Evaluates a toplevel expression as an rvalue.
-  InterpResult evaluateAsRValue(State &Parent, const Expr *E, APValue &Result);
+  bool evaluateAsRValue(State &Parent, const Expr *E, APValue &Result);
 
   /// Evaluates a toplevel initializer.
-  InterpResult evaluateAsInitializer(State &Parent, const VarDecl *VD,
- APValue &Result);
+  bool evaluateAsInitializer(State &Parent, const VarDecl *VD, APValue &Result);
 
   /// Returns the AST context.
   ASTContext &getASTContext() const { return Ctx; }
@@ -78,16 +66,14 @@
 
 private:
   /// Runs a function.
-  InterpResult Run(State &Parent, Function *Func, APValue &Result);
+  bool Run(State &Parent, Function *Func, APValue &Result);
 
   /// Checks a result fromt the interpreter.
-  InterpResult Check(State &Parent, llvm::Expected &&R);
+  bool Check(State &Parent, llvm::Expected &&R);
 
 private:
   /// Current compilation context.
   ASTContext &Ctx;
-  /// Flag to indicate if the use of the interpreter is mandatory.
-  bool ForceInterp;
   /// Interpreter stack, shared across invocations.
   InterpStack Stk;
   /// Constexpr program.
Index: clang/lib/AST/Interp/Context.cpp

[PATCH] D64146: [Clang Interpreter] Initial patch for the constexpr interpreter

2019-09-12 Thread Nandor Licker via Phabricator via cfe-commits
nand added a comment.

Thanks for looking into the problem - sorry for the delay!


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64146/new/

https://reviews.llvm.org/D64146



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D64146: [Clang Interpreter] Initial patch for the constexpr interpreter

2019-09-10 Thread Nandor Licker via Phabricator via cfe-commits
nand added a comment.

Totally missed that - thanks for noticing. I must have forgotten to remove 
stuff from the header since clang/gcc don't warn about it.
I'll get hold of a Windows machine soon-ish and I'll make sure to fix this 
problem.
Thanks!


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64146/new/

https://reviews.llvm.org/D64146



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D64146: [Clang Interpreter] Initial patch for the constexpr interpreter

2019-09-09 Thread Nandor Licker via Phabricator via cfe-commits
nand added a comment.

I am providing definitions in the C++ file - the problem is that they are not 
available in the header before the extern declaration. The methods are 
available at the site of the extern definition.
gcc and clang accept this,  so does Visual Studio 2019. This feels like an 
incorrect implementation of extern templates in Visual Studio?

I see two ways to proceed: move everything into a header (would like to avoid 
this) or silence the warning on VC++ (not great either). 
Is there a better way? Which option is less bad from these two?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64146/new/

https://reviews.llvm.org/D64146



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D64146: [Clang Interpreter] Initial patch for the constexpr interpreter

2019-09-04 Thread Nandor Licker via Phabricator via cfe-commits
nand added a reviewer: rnk.
nand added a subscriber: rnk.
nand added a comment.

@jfb suggested I add @rnk: I was wondering if you have any suggestions on how 
to fix the msvc warnings/errors? I'd be grateful if I had some feedback on what 
features of C++ I should avoid using and what I should replace them with.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64146/new/

https://reviews.llvm.org/D64146



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D64146: [Clang Interpreter] Initial patch for the constexpr interpreter

2019-09-04 Thread Nandor Licker via Phabricator via cfe-commits
nand added a comment.

The existing evaluator is not a separate library to start with. Given the 
tangling between ExprConstants.cpp and the AST nodes, I don't really see any 
elegant way of dealing with this problem.

An example of the problem is `FieldDecl::getBitWidthValue`.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64146/new/

https://reviews.llvm.org/D64146



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D64146: [Clang Interpreter] Initial patch for the constexpr interpreter

2019-09-04 Thread Nandor Licker via Phabricator via cfe-commits
nand added a comment.

Does anyone have any suggestions on how to fix the MSVC problems? I am trying 
to get access to a Windows machine, but it's not guaranteed.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64146/new/

https://reviews.llvm.org/D64146



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D64146: [Clang Interpreter] Initial patch for the constexpr interpreter

2019-09-04 Thread Nandor Licker via Phabricator via cfe-commits
nand reopened this revision.
nand added a comment.

Thanks for identifying these issues - I fixed the cycle detected by modules 
since then, however I wasn't aware of the issue with shared libs until now.


Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64146/new/

https://reviews.llvm.org/D64146



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D66808: [ConstExprPreter] Full patch of the interpreter.

2019-08-30 Thread Nandor Licker via Phabricator via cfe-commits
nand updated this revision to Diff 218131.
nand added a comment.

Added more features


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66808/new/

https://reviews.llvm.org/D66808

Files:
  clang/docs/ConstantInterpreter.rst
  clang/include/clang/AST/ASTContext.h
  clang/include/clang/Basic/DiagnosticASTKinds.td
  clang/include/clang/Basic/LangOptions.def
  clang/include/clang/Basic/OptionalDiagnostic.h
  clang/include/clang/Driver/Options.td
  clang/lib/AST/ASTContext.cpp
  clang/lib/AST/CMakeLists.txt
  clang/lib/AST/ExprConstant.cpp
  clang/lib/AST/Interp/Block.cpp
  clang/lib/AST/Interp/Block.h
  clang/lib/AST/Interp/Builtin.cpp
  clang/lib/AST/Interp/Builtin.h
  clang/lib/AST/Interp/ByteCodeEmitter.cpp
  clang/lib/AST/Interp/ByteCodeEmitter.h
  clang/lib/AST/Interp/ByteCodeExprGen.cpp
  clang/lib/AST/Interp/ByteCodeExprGen.h
  clang/lib/AST/Interp/ByteCodeGenError.cpp
  clang/lib/AST/Interp/ByteCodeGenError.h
  clang/lib/AST/Interp/ByteCodeStmtGen.cpp
  clang/lib/AST/Interp/ByteCodeStmtGen.h
  clang/lib/AST/Interp/CMakeLists.txt
  clang/lib/AST/Interp/Context.cpp
  clang/lib/AST/Interp/Context.h
  clang/lib/AST/Interp/Descriptor.cpp
  clang/lib/AST/Interp/Descriptor.h
  clang/lib/AST/Interp/Disasm.cpp
  clang/lib/AST/Interp/EvalEmitter.cpp
  clang/lib/AST/Interp/EvalEmitter.h
  clang/lib/AST/Interp/Frame.cpp
  clang/lib/AST/Interp/Frame.h
  clang/lib/AST/Interp/Function.cpp
  clang/lib/AST/Interp/Function.h
  clang/lib/AST/Interp/HeapUtils.cpp
  clang/lib/AST/Interp/HeapUtils.h
  clang/lib/AST/Interp/Integral.h
  clang/lib/AST/Interp/Interp.cpp
  clang/lib/AST/Interp/Interp.h
  clang/lib/AST/Interp/InterpFrame.cpp
  clang/lib/AST/Interp/InterpFrame.h
  clang/lib/AST/Interp/InterpStack.cpp
  clang/lib/AST/Interp/InterpStack.h
  clang/lib/AST/Interp/InterpState.cpp
  clang/lib/AST/Interp/InterpState.h
  clang/lib/AST/Interp/Opcode.h
  clang/lib/AST/Interp/Opcodes.td
  clang/lib/AST/Interp/Pointer.cpp
  clang/lib/AST/Interp/Pointer.h
  clang/lib/AST/Interp/Program.cpp
  clang/lib/AST/Interp/Program.h
  clang/lib/AST/Interp/Real.h
  clang/lib/AST/Interp/Record.cpp
  clang/lib/AST/Interp/Record.h
  clang/lib/AST/Interp/Source.cpp
  clang/lib/AST/Interp/Source.h
  clang/lib/AST/Interp/State.cpp
  clang/lib/AST/Interp/State.h
  clang/lib/AST/Interp/Type.cpp
  clang/lib/AST/Interp/Type.h
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/test/AST/Interp/alignof.cpp
  clang/test/AST/Interp/arg_struct.cpp
  clang/test/AST/Interp/array.cpp
  clang/test/AST/Interp/array_in_array.cpp
  clang/test/AST/Interp/array_loop_init.cpp
  clang/test/AST/Interp/bitfield.cpp
  clang/test/AST/Interp/boolean.cpp
  clang/test/AST/Interp/bound_member_ptr.cpp
  clang/test/AST/Interp/call.cpp
  clang/test/AST/Interp/case_range.cpp
  clang/test/AST/Interp/cast.cpp
  clang/test/AST/Interp/compound_assign.cpp
  clang/test/AST/Interp/cond.cpp
  clang/test/AST/Interp/default_cons.cpp
  clang/test/AST/Interp/designated_init.cpp
  clang/test/AST/Interp/double_to_int.cpp
  clang/test/AST/Interp/dummy.cpp
  clang/test/AST/Interp/enum.cpp
  clang/test/AST/Interp/extern.cpp
  clang/test/AST/Interp/float.cpp
  clang/test/AST/Interp/flow.cpp
  clang/test/AST/Interp/for_range.cpp
  clang/test/AST/Interp/funcptr.cpp
  clang/test/AST/Interp/global.cpp
  clang/test/AST/Interp/inheritance.cpp
  clang/test/AST/Interp/init.cpp
  clang/test/AST/Interp/init_list_int.cpp
  clang/test/AST/Interp/init_list_ptr.cpp
  clang/test/AST/Interp/int128.cpp
  clang/test/AST/Interp/int64.cpp
  clang/test/AST/Interp/lifetime.cpp
  clang/test/AST/Interp/locals.cpp
  clang/test/AST/Interp/logical.cpp
  clang/test/AST/Interp/loop.cpp
  clang/test/AST/Interp/member_fn.cpp
  clang/test/AST/Interp/member_fn_virtual.cpp
  clang/test/AST/Interp/member_ptr.cpp
  clang/test/AST/Interp/member_ptr_ambiguity.cpp
  clang/test/AST/Interp/member_ptr_derived.cpp
  clang/test/AST/Interp/member_ptr_explicit_path.cpp
  clang/test/AST/Interp/member_ptr_missing.cpp
  clang/test/AST/Interp/member_ptr_print.cpp
  clang/test/AST/Interp/member_ptr_wrong_path.cpp
  clang/test/AST/Interp/method.cpp
  clang/test/AST/Interp/null_method.cpp
  clang/test/AST/Interp/nullptr.cpp
  clang/test/AST/Interp/nullptr_struct.cpp
  clang/test/AST/Interp/operator.cpp
  clang/test/AST/Interp/overflow.cpp
  clang/test/AST/Interp/past_end.cpp
  clang/test/AST/Interp/ptr.cpp
  clang/test/AST/Interp/ptr_derived_cast.cpp
  clang/test/AST/Interp/ptrdiff.cpp
  clang/test/AST/Interp/ptrdiff_overflow.cpp
  clang/test/AST/Interp/pure_virt_ind.cpp
  clang/test/AST/Interp/read_only.cpp
  clang/test/AST/Interp/ref_field.cpp
  clang/test/AST/Interp/relocation.cpp
  clang/test/AST/Interp/return.cpp
  clang/test/AST/Interp/rvo.cpp
  clang/test/AST/Interp/scoping.cpp
  clang/test/AST/Interp/selfref.cpp
  clang/test/AST/Interp/set_field.cpp
  clang/test/AST/Interp/shift.cpp
  clang/test/AST/Interp/sizeof.cpp
  clang/test/AST/Interp/stack_trace.

[PATCH] D64146: [Clang Interpreter] Initial patch for the constexpr interpreter

2019-08-13 Thread Nandor Licker via Phabricator via cfe-commits
nand added a comment.

The old path-based approach is slow for most operations, while the new 
pointer-based approach is fast for the most common ones. 
For read/write/update operations, it is enough to check the pointer and at most 
a single descriptor to ensure whether the operation 
can be performed. For some operations, such as some pointer comparisons, in the 
worst case the old-style path can be reproduced by
following the pointers produced through the getBase method, allowing us to 
implement everything.

Extern objects are handled by allocating memory for them, allowing pointers to 
those regions to exist, but marking the actual storage
as extern/uninitialized and preventing reads/writes to that storage.

Some details of corner cases are not clear at this point, but the fact that we 
can reproduce full paths and have space to store any special
bits gives me the confidence that we can converge to a full implementation.

I want to stress again the fact that C++ has an insane number of features and I 
am focusing on implementing as many of them, leaving a 
path towards future optimisations open. I do not want to clobber initial 
patches with optimisations that would increase complexity - the
few things we do with direct local reads/writes and improved loops already 
yield significant speedupds.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64146/new/

https://reviews.llvm.org/D64146



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D64146: [Clang Interpreter] Initial patch for the constexpr interpreter

2019-08-13 Thread Nandor Licker via Phabricator via cfe-commits
nand added a comment.

updated diff, implemented requested changes




Comment at: clang/include/clang/Basic/LangOptions.def:291-294
+BENIGN_LANGOPT(EnableClangInterp, 1, 0,
+   "enable the experimental clang interpreter")
+BENIGN_LANGOPT(ForceClangInterp, 1, 0,
+   "force the use of the experimental constexpr interpreter")

rsmith wrote:
> "Clang" is redundant here (what else could it be?). If we're calling the new 
> thing "interp" internally, then I guess "EnableInterp" and "ForceInterp" seem 
> OK, but given that this is just scaffolding until the new interpreter is 
> done, maybe "EnableNewInterp" and "ForceNewInterp" would be better. 
> Suggestion:
> 
> ```
> BENIGN_LANGOPT(EnableNewInterp, 1, 0,
>"enable the experimental new constexpr interpreter")
> BENIGN_LANGOPT(ForceNewInterp, 1, 0,
>"force the use of the experimental new constexpr interpreter")
> ```
The goal is to evaluate everything that is constant - I would like to avoid 
using constexpr specifically in the name.



Comment at: clang/lib/AST/ExprConstant.cpp:5039-5040
+  return true;
+case interp::InterpResult::Fail:
+  return false;
+case interp::InterpResult::Bail:

rsmith wrote:
> Missing a check for `ForceClangInterp` here.
This is intended - if the interpreter bails and ForceInterp is set, we emit a 
diagnostic in Context, promoting the error to a failure.



Comment at: clang/lib/AST/Interp/ByteCodeGen.cpp:352-381
+case BO_LAnd: {
+  if (!this->Visit(LHS))
+return false;
+  auto Short = this->getLabel();
+  if (!this->emitDup(*TypeLHS, BO))
+return false;
+  if (!this->jumpFalse(Short))

rsmith wrote:
> Have you considered how you will support Clang's current constant folding of 
> `&&` and `||` expressions where the left-hand side is non-constant but the 
> right hand side is a false or true constant (respectively)?
Same as with statement expressions in the evaluating emitter - some sort of 
closure which compiles and executes when triggered.



Comment at: clang/lib/AST/Interp/ByteCodeGen.cpp:536
+} else {
+  // If the param is a pointer, we can dereference a dummy value.
+  if (PD->getType()->hasPointerRepresentation()) {

rsmith wrote:
> We can, but should we?
> 
> I would think the only time we can reach this case is when we're 
> constant-evaluating an expression within a function and that expression names 
> a function parameter, and in that case, the expression should be treated as 
> non-constant. We should have a more direct way to represent "if you get here, 
> the evaluation is non-constant, with this reason" in the bytecode.
We absolutely need this to emit the warning:
```
constexpr int callee_ptr(int *beg, int *end) {
  const int x = 2147483647;
  *beg = x + x; // expected-warning {{overflow in expression; result is -2 with 
type 'int'}}\
// expected-note 3{{value 4294967294 is outside the range of 
representable values of type 'int'}}
  return *beg;
}
```



Comment at: clang/lib/AST/Interp/ByteCodeGen.cpp:546
+  }
+  if (auto *VD = dyn_cast(DE->getDecl())) {
+auto It = Locals.find(VD);

rsmith wrote:
> The above `ParmVarDecl` case can fall through into here, because a 
> `ParmVarDecl` is a `VarDecl`. Is that what you intended?
> 
> Do you actually need to treat locals and parameters separately? This would 
> seem simpler if you could model them as being the same thing.
Refactored + fixed this by moving stuff to separate functions.



Comment at: clang/lib/AST/Interp/ByteCodeGen.cpp:647-662
+  case PT_Sint8:
+return this->emitConstSint8(Value.getSExtValue(), E);
+  case PT_Uint8:
+return this->emitConstUint8(Value.getZExtValue(), E);
+  case PT_Sint16:
+return this->emitConstSint16(Value.getSExtValue(), E);
+  case PT_Uint16:

rsmith wrote:
> I'd like to see this generated from a `.def` file, rather than enumerating 
> the various currently-supported integer types in many different places. The 
> goal should be that adding support for a new integer type / size (say we 
> start supporting a target with 48 bit integers) should require making changes 
> in only one place. Case in point: you're currently missing support for 
> 128-bit integers, which Clang does support across many targets.
This is the only case where such a switch occurs - there is another for zero 
initialisation, but it's quite different. A def which would capture the little 
common functionality would be quite ugly, so I would like to avoid it.

As for other integers, there won't be support for any. There are two more 
branches for the fixed-point catch-all fallback.



Comment at: clang/lib/AST/Interp/ByteCodeGen.h:40
+class ByteCodeGen : public ConstStmtVisitor, bool>,
+ 

[PATCH] D64146: [ConstExprPreter][WIP] Initial patch for the constexpr interpreter

2019-07-31 Thread Nandor Licker via Phabricator via cfe-commits
nand marked 40 inline comments as done.
nand added a comment.

I have applied most of the changes you suggested to my HEAD which had 
significantly more functionality, including a replacement of Opcodes.in with 
TableGen.
Quite a few of your concerns are answered by the features I have added between 
submitting the patch and now. The interpreter now stands at ~6k LOC.

Should I update the diff with an interpreter trimmed down to the functionality 
of the current diff (~3k LOC) or post the full interpreter now? What would be 
easier to review?




Comment at: clang/lib/AST/ExprVM/Compiler.cpp:88
+  Params.insert({ParamDecl, ParamOffset});
+  ParamOffset += align(Size);
+  Args.push_back(*T);

rsmith wrote:
> What happens if this overflows (due to many large local variables)?
Overflow happens here if a function takes more than a few million arguments. I 
think clang would die before it gets here.



Comment at: clang/lib/AST/ExprVM/Compiler.cpp:488-503
+Error Compiler::discard(const Expr *DE) {
+  switch (DE->getStmtClass()) {
+  case Stmt::BinaryOperatorClass:
+return discardBinaryOperator(static_cast(DE));
+  default:
+if (auto E = Visit(DE))
+  return E;

rsmith wrote:
> I'm uncomfortable about this: it looks like you're heading towards 
> duplicating a large portion of the bytecode generation depending on whether 
> the result is used. Can we do better somehow? (Eg, in CodeGen, at least for 
> aggregates, we use the same code but track whether the destination is used or 
> not.)
I'd like to do this in a future diff, once we add support for more constructs 
which discard their results.



Comment at: clang/lib/AST/ExprVM/InterpFrame.h:89-90
+  char *Args = nullptr;
+  /// Fixed, initial storage for known local variables.
+  std::unique_ptr Locals;
+};

rsmith wrote:
> Separate allocation for each frame seems wasteful. Have you considered using 
> a slab-allocated stack or similar? (Eg, allocate a large block up front and 
> allocate the locals from that, and allocate more blocks if the first one is 
> exhausted; you can cache the blocks on the `vm::Context` for reuse with no 
> extra round-trips to the heap.)
Yes, I considered allocating this on the stack - I just don't want to add that 
complexity to the interpreter yet. I like to avoid changing this until it 
becomes a noticeable performance problem.



Comment at: clang/lib/AST/ExprVM/Pointer.h:30
+
+/// Describes a memory block - generated once by the compiler.
+struct Descriptor {

rsmith wrote:
> How is this going to work for subobjects? We can't generate the full space of 
> all possible descriptors, as that would be unmanageable for large arrays of 
> complicated types.
Subobjects will have pointers to descriptors embedded into their data - a 
pointer inside a block can follow that chain of descriptors up to the root.



Comment at: clang/lib/AST/ExprVM/Pointer.h:36-39
+  /// Size of the object.
+  unsigned Size;
+  /// Size of an element.
+  unsigned ElemSize;

rsmith wrote:
> Please use a distinct type for representing size-in-the-interpreter, to avoid 
> confusion and bugs when dealing with code that must manage both compile-time 
> sizes and runtime sizes. And please use `CharUnits` for representing 
> sizes-at-runtime.
I've added an alias to be used for the sizes of object as determined by the 
interpreter - CharUnits will be used when interfacing with APValue.



Comment at: clang/lib/AST/ExprVM/Pointer.h:40-49
+  /// Type of the elements.
+  PrimType ElemType;
+  /// Flag indicating if the descriptor is mutable.
+  bool IsMutable = false;
+  /// Flag indicating if the object is an array.
+  bool IsArray = false;
+  /// Flag indicating if the object is a global.

rsmith wrote:
> Consider packing these 5 members into 4 bytes. 
I'd like to avoid packing stuff for now, makes it harder to change things later 
and it's not a performance problem yet.



Comment at: clang/lib/AST/ExprVM/Program.h:105
+  /// Program bytecode.
+  std::vector Code;
+  /// Mapping from bytecode offsets to source locations.

rsmith wrote:
> If `CodePtr` is a plain pointer, using a single flat vector here seems 
> dangerous; you'll have invalidation issues if you ever trigger creation of a 
> `Function` while evaluating, which seems like something that will happen in 
> practice, eg:
> 
> ```
> constexpr int f();
> constexpr int g() { return f(); }
> constexpr int f() { return 0; } // or imported from a module at this point
> constexpr int k = g(); // evaluation of this call triggers generation of code 
> for f
> ```
This wouldn't have been a problem, but the compilation of default constructors 
caused issues. Now the compiler can recursively invoke itself.



Comment at: clang/lib/AST/ExprVM/Program.h:106-107
+

[PATCH] D64146: [ConstExprPreter][WIP] Initial patch for the constexpr interpreter

2019-07-29 Thread Nandor Licker via Phabricator via cfe-commits
nand marked 10 inline comments as done.
nand added a comment.

We can add a separate integer type which tracks all the additional information 
required by `__builtin_constant_p` and compile all integers to it in this 
context. A later patch added an APInt fallback to the interpreter if an 
integral cannot be mapped to a type supported by the VM - this mechanism could 
be used to implement the fallback for contexts which cast pointers to integers.




Comment at: clang/lib/AST/ExprVM/Compiler.h:125
+/// Size of the local, in bytes.
+unsigned Size;
+  };

jfb wrote:
> `ByteSize` since it's the size in bytes :)
I've removed the size field since it's not going to be used, but left the 
structure since it will gain other fields in future patches.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64146/new/

https://reviews.llvm.org/D64146



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D64146: [ConstExprPreter][WIP] Initial patch for the constexpr interpreter

2019-07-29 Thread Nandor Licker via Phabricator via cfe-commits
nand added a comment.

> How do you intend to represent pointers cast to integer types? Allocating 64 
> bits of state for a 64-bit integer is insufficient to model that case.

Is this ever going to be allowed in constexpr? If that is the case, we'll add a 
separate type for all integers which are large enough to hold a pointer, a 
tagged union indicating whether the value is a number or a pointer. This would 
add significant overhead, but I don't see any other way which can correctly 
diagnose UB when casting a random integer to a pointer.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64146/new/

https://reviews.llvm.org/D64146



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits