mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-14 20:03:14 +01:00
This fixes a segfault with associative array literals of arrays of associative array literals, which occured because of arrayLiteralToConst not handling null values properly. Ensuring that null pointers are handled correctly in all toConstElem callers is much more error-prone than just returning an LLVM undef, an error is emitted anyway. The root of the problem is actually in the kludgly implementation of AssocArrayLiteral::toElem, we should revisit this at some point.
2049 lines
59 KiB
C++
2049 lines
59 KiB
C++
|
|
// Compiler implementation of the D programming language
|
|
// Copyright (c) 1999-2012 by Digital Mars
|
|
// All Rights Reserved
|
|
// written by Walter Bright
|
|
// http://www.digitalmars.com
|
|
// License for redistribution is by either the Artistic License
|
|
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
|
// See the included readme.txt for details.
|
|
|
|
#ifndef DMD_EXPRESSION_H
|
|
#define DMD_EXPRESSION_H
|
|
|
|
#include "mars.h"
|
|
#include "identifier.h"
|
|
#include "lexer.h"
|
|
#include "arraytypes.h"
|
|
#include "intrange.h"
|
|
|
|
class Type;
|
|
class TypeVector;
|
|
struct Scope;
|
|
class TupleDeclaration;
|
|
class VarDeclaration;
|
|
class FuncDeclaration;
|
|
class FuncLiteralDeclaration;
|
|
class Declaration;
|
|
class CtorDeclaration;
|
|
class NewDeclaration;
|
|
class Dsymbol;
|
|
class Import;
|
|
class Module;
|
|
class ScopeDsymbol;
|
|
struct InlineCostState;
|
|
struct InlineDoState;
|
|
struct InlineScanState;
|
|
class Expression;
|
|
class Declaration;
|
|
class AggregateDeclaration;
|
|
class StructDeclaration;
|
|
class TemplateInstance;
|
|
class TemplateDeclaration;
|
|
class ClassDeclaration;
|
|
struct HdrGenState;
|
|
class BinExp;
|
|
struct InterState;
|
|
#if IN_DMD
|
|
struct Symbol; // back end symbol
|
|
#endif
|
|
class OverloadSet;
|
|
class Initializer;
|
|
class StringExp;
|
|
class ArrayExp;
|
|
class SliceExp;
|
|
#if IN_LLVM
|
|
class AssignExp;
|
|
class SymbolDeclaration;
|
|
#endif
|
|
|
|
enum TOK;
|
|
|
|
#if IN_DMD
|
|
// Back end
|
|
struct IRState;
|
|
struct dt_t;
|
|
#endif
|
|
|
|
#ifdef IN_GCC
|
|
typedef union tree_node elem;
|
|
#elif IN_LLVM
|
|
class DValue; typedef class DValue elem;
|
|
#else
|
|
struct elem;
|
|
#endif
|
|
|
|
#if IN_LLVM
|
|
struct IRState;
|
|
namespace llvm {
|
|
class Constant;
|
|
class ConstantInt;
|
|
class GlobalVariable;
|
|
class StructType;
|
|
class Value;
|
|
}
|
|
#endif
|
|
|
|
void initPrecedence();
|
|
|
|
typedef int (*apply_fp_t)(Expression *, void *);
|
|
|
|
Expression *resolveProperties(Scope *sc, Expression *e);
|
|
Expression *resolvePropertiesOnly(Scope *sc, Expression *e1);
|
|
void accessCheck(Loc loc, Scope *sc, Expression *e, Declaration *d);
|
|
Expression *build_overload(Loc loc, Scope *sc, Expression *ethis, Expression *earg, Dsymbol *d);
|
|
Dsymbol *search_function(ScopeDsymbol *ad, Identifier *funcid);
|
|
void argExpTypesToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs);
|
|
void argsToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs);
|
|
void expandTuples(Expressions *exps);
|
|
TupleDeclaration *isAliasThisTuple(Expression *e);
|
|
int expandAliasThisTuples(Expressions *exps, size_t starti = 0);
|
|
FuncDeclaration *hasThis(Scope *sc);
|
|
Expression *fromConstInitializer(int result, Expression *e);
|
|
int arrayExpressionCanThrow(Expressions *exps, bool mustNotThrow);
|
|
TemplateDeclaration *getFuncTemplateDecl(Dsymbol *s);
|
|
Expression *valueNoDtor(Expression *e);
|
|
int modifyFieldVar(Loc loc, Scope *sc, VarDeclaration *var, Expression *e1);
|
|
#if DMDV2
|
|
Expression *resolveAliasThis(Scope *sc, Expression *e);
|
|
Expression *callCpCtor(Scope *sc, Expression *e);
|
|
#endif
|
|
Expression *resolveOpDollar(Scope *sc, ArrayExp *ae);
|
|
Expression *resolveOpDollar(Scope *sc, SliceExp *se);
|
|
Expressions *arrayExpressionSemantic(Expressions *exps, Scope *sc);
|
|
|
|
/* Run CTFE on the expression, but allow the expression to be a TypeExp
|
|
* or a tuple containing a TypeExp. (This is required by pragma(msg)).
|
|
*/
|
|
Expression *ctfeInterpretForPragmaMsg(Expression *e);
|
|
|
|
/* Interpreter: what form of return value expression is required?
|
|
*/
|
|
enum CtfeGoal
|
|
{ ctfeNeedRvalue, // Must return an Rvalue
|
|
ctfeNeedLvalue, // Must return an Lvalue
|
|
ctfeNeedAnyValue, // Can return either an Rvalue or an Lvalue
|
|
ctfeNeedLvalueRef,// Must return a reference to an Lvalue (for ref types)
|
|
ctfeNeedNothing // The return value is not required
|
|
};
|
|
|
|
#define WANTflags 1
|
|
#define WANTvalue 2
|
|
// Same as WANTvalue, but also expand variables as far as possible
|
|
#define WANTexpand 8
|
|
|
|
class Expression : public RootObject
|
|
{
|
|
public:
|
|
Loc loc; // file location
|
|
TOK op; // handy to minimize use of dynamic_cast
|
|
Type *type; // !=NULL means that semantic() has been run
|
|
unsigned char size; // # of bytes in Expression so we can copy() it
|
|
unsigned char parens; // if this is a parenthesized expression
|
|
|
|
Expression(Loc loc, TOK op, int size);
|
|
static void init();
|
|
Expression *copy();
|
|
virtual Expression *syntaxCopy();
|
|
virtual int apply(apply_fp_t fp, void *param);
|
|
virtual Expression *semantic(Scope *sc);
|
|
Expression *trySemantic(Scope *sc);
|
|
|
|
int dyncast() { return DYNCAST_EXPRESSION; } // kludge for template.isExpression()
|
|
|
|
void print();
|
|
char *toChars();
|
|
virtual void dump(int indent);
|
|
void error(const char *format, ...);
|
|
void warning(const char *format, ...);
|
|
void deprecation(const char *format, ...);
|
|
virtual int rvalue();
|
|
|
|
static Expression *combine(Expression *e1, Expression *e2);
|
|
static Expressions *arraySyntaxCopy(Expressions *exps);
|
|
|
|
virtual dinteger_t toInteger();
|
|
virtual uinteger_t toUInteger();
|
|
virtual real_t toReal();
|
|
virtual real_t toImaginary();
|
|
virtual complex_t toComplex();
|
|
virtual StringExp *toString();
|
|
virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
virtual void toMangleBuffer(OutBuffer *buf);
|
|
virtual int isLvalue();
|
|
virtual Expression *toLvalue(Scope *sc, Expression *e);
|
|
virtual Expression *modifiableLvalue(Scope *sc, Expression *e);
|
|
virtual Expression *implicitCastTo(Scope *sc, Type *t);
|
|
virtual MATCH implicitConvTo(Type *t);
|
|
virtual IntRange getIntRange();
|
|
virtual Expression *castTo(Scope *sc, Type *t);
|
|
virtual Expression *inferType(Type *t, int flag = 0, Scope *sc = NULL, TemplateParameters *tparams = NULL);
|
|
virtual void checkEscape();
|
|
virtual void checkEscapeRef();
|
|
virtual Expression *resolveLoc(Loc loc, Scope *sc);
|
|
void checkScalar();
|
|
void checkNoBool();
|
|
Expression *checkIntegral();
|
|
Expression *checkArithmetic();
|
|
void checkDeprecated(Scope *sc, Dsymbol *s);
|
|
void checkPurity(Scope *sc, FuncDeclaration *f);
|
|
void checkPurity(Scope *sc, VarDeclaration *v);
|
|
void checkSafety(Scope *sc, FuncDeclaration *f);
|
|
bool checkPostblit(Scope *sc, Type *t);
|
|
virtual int checkModifiable(Scope *sc, int flag = 0);
|
|
virtual Expression *checkToBoolean(Scope *sc);
|
|
virtual Expression *addDtorHook(Scope *sc);
|
|
Expression *checkToPointer();
|
|
Expression *addressOf(Scope *sc);
|
|
Expression *deref();
|
|
Expression *integralPromotions(Scope *sc);
|
|
Expression *isTemp();
|
|
|
|
Expression *toDelegate(Scope *sc, Type *t);
|
|
|
|
virtual Expression *optimize(int result, bool keepLvalue = false);
|
|
|
|
// Entry point for CTFE.
|
|
// A compile-time result is required. Give an error if not possible
|
|
Expression *ctfeInterpret();
|
|
|
|
// Implementation of CTFE for this expression
|
|
virtual Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
|
|
|
virtual int isConst();
|
|
virtual int isBool(int result);
|
|
virtual int isBit();
|
|
bool hasSideEffect();
|
|
void discardValue();
|
|
void useValue();
|
|
int canThrow(bool mustNotThrow);
|
|
|
|
virtual int inlineCost3(InlineCostState *ics);
|
|
virtual Expression *doInline(InlineDoState *ids);
|
|
virtual Expression *inlineScan(InlineScanState *iss);
|
|
Expression *inlineCopy(Scope *sc);
|
|
|
|
// For operator overloading
|
|
virtual int isCommutative();
|
|
virtual Identifier *opId();
|
|
virtual Identifier *opId_r();
|
|
|
|
// For array ops
|
|
virtual void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
|
|
virtual Expression *buildArrayLoop(Parameters *fparams);
|
|
int isArrayOperand();
|
|
|
|
// Back end
|
|
virtual elem *toElem(IRState *irs);
|
|
elem *toElemDtor(IRState *irs);
|
|
#if IN_LLVM
|
|
/// Emits an LLVM constant corresponding to the expression.
|
|
///
|
|
/// Due to the current implementation of AssocArrayLiteralExp::toElem,the
|
|
/// implementations have to be able to handle being called on expressions
|
|
/// that are not actually constant. In such a case, an LLVM undef of the
|
|
/// expected type should be returned (_not_ null).
|
|
virtual llvm::Constant *toConstElem(IRState *irs);
|
|
|
|
virtual void cacheLvalue(IRState* irs);
|
|
llvm::Value* cachedLvalue;
|
|
|
|
virtual AssignExp* isAssignExp() { return NULL; }
|
|
#else
|
|
virtual dt_t **toDt(dt_t **pdt);
|
|
#endif
|
|
};
|
|
|
|
class IntegerExp : public Expression
|
|
{
|
|
public:
|
|
dinteger_t value;
|
|
|
|
IntegerExp(Loc loc, dinteger_t value, Type *type);
|
|
IntegerExp(dinteger_t value);
|
|
bool equals(RootObject *o);
|
|
Expression *semantic(Scope *sc);
|
|
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
|
char *toChars();
|
|
void dump(int indent);
|
|
IntRange getIntRange();
|
|
dinteger_t toInteger();
|
|
real_t toReal();
|
|
real_t toImaginary();
|
|
complex_t toComplex();
|
|
int isConst();
|
|
int isBool(int result);
|
|
MATCH implicitConvTo(Type *t);
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
void toMangleBuffer(OutBuffer *buf);
|
|
Expression *toLvalue(Scope *sc, Expression *e);
|
|
elem *toElem(IRState *irs);
|
|
#if IN_LLVM
|
|
llvm::Constant *toConstElem(IRState *irs);
|
|
#else
|
|
dt_t **toDt(dt_t **pdt);
|
|
#endif
|
|
};
|
|
|
|
class ErrorExp : public IntegerExp
|
|
{
|
|
public:
|
|
ErrorExp();
|
|
|
|
Expression *implicitCastTo(Scope *sc, Type *t);
|
|
MATCH implicitConvTo(Type *t);
|
|
Expression *castTo(Scope *sc, Type *t);
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
Expression *toLvalue(Scope *sc, Expression *e);
|
|
};
|
|
|
|
class RealExp : public Expression
|
|
{
|
|
public:
|
|
real_t value;
|
|
|
|
RealExp(Loc loc, real_t value, Type *type);
|
|
bool equals(RootObject *o);
|
|
Expression *semantic(Scope *sc);
|
|
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
|
char *toChars();
|
|
dinteger_t toInteger();
|
|
uinteger_t toUInteger();
|
|
real_t toReal();
|
|
real_t toImaginary();
|
|
complex_t toComplex();
|
|
Expression *castTo(Scope *sc, Type *t);
|
|
int isConst();
|
|
int isBool(int result);
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
void toMangleBuffer(OutBuffer *buf);
|
|
elem *toElem(IRState *irs);
|
|
#if IN_LLVM
|
|
llvm::Constant *toConstElem(IRState *irs);
|
|
#else
|
|
dt_t **toDt(dt_t **pdt);
|
|
#endif
|
|
};
|
|
|
|
class ComplexExp : public Expression
|
|
{
|
|
public:
|
|
complex_t value;
|
|
|
|
ComplexExp(Loc loc, complex_t value, Type *type);
|
|
bool equals(RootObject *o);
|
|
Expression *semantic(Scope *sc);
|
|
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
|
char *toChars();
|
|
dinteger_t toInteger();
|
|
uinteger_t toUInteger();
|
|
real_t toReal();
|
|
real_t toImaginary();
|
|
complex_t toComplex();
|
|
Expression *castTo(Scope *sc, Type *t);
|
|
int isConst();
|
|
int isBool(int result);
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
void toMangleBuffer(OutBuffer *buf);
|
|
elem *toElem(IRState *irs);
|
|
#if IN_LLVM
|
|
llvm::Constant *toConstElem(IRState *irs);
|
|
#else
|
|
dt_t **toDt(dt_t **pdt);
|
|
#endif
|
|
};
|
|
|
|
class IdentifierExp : public Expression
|
|
{
|
|
public:
|
|
Identifier *ident;
|
|
Declaration *var;
|
|
|
|
IdentifierExp(Loc loc, Identifier *ident);
|
|
Expression *semantic(Scope *sc);
|
|
char *toChars();
|
|
void dump(int indent);
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
int isLvalue();
|
|
Expression *toLvalue(Scope *sc, Expression *e);
|
|
};
|
|
|
|
class DollarExp : public IdentifierExp
|
|
{
|
|
public:
|
|
DollarExp(Loc loc);
|
|
};
|
|
|
|
class DsymbolExp : public Expression
|
|
{
|
|
public:
|
|
Dsymbol *s;
|
|
bool hasOverloads;
|
|
|
|
DsymbolExp(Loc loc, Dsymbol *s, bool hasOverloads = false);
|
|
Expression *semantic(Scope *sc);
|
|
char *toChars();
|
|
void dump(int indent);
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
int isLvalue();
|
|
Expression *toLvalue(Scope *sc, Expression *e);
|
|
};
|
|
|
|
class ThisExp : public Expression
|
|
{
|
|
public:
|
|
Declaration *var;
|
|
|
|
ThisExp(Loc loc);
|
|
Expression *semantic(Scope *sc);
|
|
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
|
int isBool(int result);
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
int isLvalue();
|
|
Expression *toLvalue(Scope *sc, Expression *e);
|
|
Expression *modifiableLvalue(Scope *sc, Expression *e);
|
|
|
|
int inlineCost3(InlineCostState *ics);
|
|
Expression *doInline(InlineDoState *ids);
|
|
//Expression *inlineScan(InlineScanState *iss);
|
|
|
|
elem *toElem(IRState *irs);
|
|
};
|
|
|
|
class SuperExp : public ThisExp
|
|
{
|
|
public:
|
|
SuperExp(Loc loc);
|
|
Expression *semantic(Scope *sc);
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
|
|
Expression *doInline(InlineDoState *ids);
|
|
//Expression *inlineScan(InlineScanState *iss);
|
|
};
|
|
|
|
class NullExp : public Expression
|
|
{
|
|
public:
|
|
unsigned char committed; // !=0 if type is committed
|
|
|
|
NullExp(Loc loc, Type *t = NULL);
|
|
bool equals(RootObject *o);
|
|
Expression *semantic(Scope *sc);
|
|
int isBool(int result);
|
|
int isConst();
|
|
StringExp *toString();
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
void toMangleBuffer(OutBuffer *buf);
|
|
MATCH implicitConvTo(Type *t);
|
|
Expression *castTo(Scope *sc, Type *t);
|
|
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
|
elem *toElem(IRState *irs);
|
|
#if IN_LLVM
|
|
llvm::Constant *toConstElem(IRState *irs);
|
|
#else
|
|
dt_t **toDt(dt_t **pdt);
|
|
#endif
|
|
};
|
|
|
|
class StringExp : public Expression
|
|
{
|
|
public:
|
|
void *string; // char, wchar, or dchar data
|
|
size_t len; // number of chars, wchars, or dchars
|
|
unsigned char sz; // 1: char, 2: wchar, 4: dchar
|
|
unsigned char committed; // !=0 if type is committed
|
|
utf8_t postfix; // 'c', 'w', 'd'
|
|
bool ownedByCtfe; // true = created in CTFE
|
|
|
|
StringExp(Loc loc, char *s);
|
|
StringExp(Loc loc, void *s, size_t len);
|
|
StringExp(Loc loc, void *s, size_t len, utf8_t postfix);
|
|
//Expression *syntaxCopy();
|
|
bool equals(RootObject *o);
|
|
Expression *semantic(Scope *sc);
|
|
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
|
size_t length();
|
|
StringExp *toString();
|
|
StringExp *toUTF8(Scope *sc);
|
|
Expression *implicitCastTo(Scope *sc, Type *t);
|
|
MATCH implicitConvTo(Type *t);
|
|
Expression *castTo(Scope *sc, Type *t);
|
|
int compare(RootObject *obj);
|
|
int isBool(int result);
|
|
int isLvalue();
|
|
Expression *toLvalue(Scope *sc, Expression *e);
|
|
Expression *modifiableLvalue(Scope *sc, Expression *e);
|
|
unsigned charAt(size_t i);
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
void toMangleBuffer(OutBuffer *buf);
|
|
elem *toElem(IRState *irs);
|
|
#if IN_LLVM
|
|
llvm::Constant *toConstElem(IRState *irs);
|
|
#else
|
|
dt_t **toDt(dt_t **pdt);
|
|
#endif
|
|
};
|
|
|
|
// Tuple
|
|
|
|
class TupleExp : public Expression
|
|
{
|
|
public:
|
|
Expression *e0; // side-effect part
|
|
/* Tuple-field access may need to take out its side effect part.
|
|
* For example:
|
|
* foo().tupleof
|
|
* is rewritten as:
|
|
* (ref __tup = foo(); tuple(__tup.field0, __tup.field1, ...))
|
|
* The declaration of temporary variable __tup will be stored in TupleExp::e0.
|
|
*/
|
|
Expressions *exps;
|
|
|
|
TupleExp(Loc loc, Expression *e0, Expressions *exps);
|
|
TupleExp(Loc loc, Expressions *exps);
|
|
TupleExp(Loc loc, TupleDeclaration *tup);
|
|
Expression *syntaxCopy();
|
|
int apply(apply_fp_t fp, void *param);
|
|
bool equals(RootObject *o);
|
|
Expression *semantic(Scope *sc);
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
void checkEscape();
|
|
Expression *optimize(int result, bool keepLvalue = false);
|
|
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
|
Expression *castTo(Scope *sc, Type *t);
|
|
elem *toElem(IRState *irs);
|
|
|
|
Expression *doInline(InlineDoState *ids);
|
|
Expression *inlineScan(InlineScanState *iss);
|
|
};
|
|
|
|
class ArrayLiteralExp : public Expression
|
|
{
|
|
public:
|
|
Expressions *elements;
|
|
bool ownedByCtfe; // true = created in CTFE
|
|
|
|
ArrayLiteralExp(Loc loc, Expressions *elements);
|
|
ArrayLiteralExp(Loc loc, Expression *e);
|
|
|
|
Expression *syntaxCopy();
|
|
int apply(apply_fp_t fp, void *param);
|
|
bool equals(RootObject *o);
|
|
Expression *semantic(Scope *sc);
|
|
int isBool(int result);
|
|
elem *toElem(IRState *irs);
|
|
StringExp *toString();
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
void toMangleBuffer(OutBuffer *buf);
|
|
Expression *optimize(int result, bool keepLvalue = false);
|
|
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
|
MATCH implicitConvTo(Type *t);
|
|
Expression *castTo(Scope *sc, Type *t);
|
|
Expression *inferType(Type *t, int flag = 0, Scope *sc = NULL, TemplateParameters *tparams = NULL);
|
|
#if IN_LLVM
|
|
llvm::Constant *toConstElem(IRState *irs);
|
|
#else
|
|
dt_t **toDt(dt_t **pdt);
|
|
#endif
|
|
|
|
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
|
|
Expression *buildArrayLoop(Parameters *fparams);
|
|
|
|
Expression *doInline(InlineDoState *ids);
|
|
Expression *inlineScan(InlineScanState *iss);
|
|
};
|
|
|
|
class AssocArrayLiteralExp : public Expression
|
|
{
|
|
public:
|
|
Expressions *keys;
|
|
Expressions *values;
|
|
bool ownedByCtfe; // true = created in CTFE
|
|
|
|
AssocArrayLiteralExp(Loc loc, Expressions *keys, Expressions *values);
|
|
|
|
Expression *syntaxCopy();
|
|
int apply(apply_fp_t fp, void *param);
|
|
Expression *semantic(Scope *sc);
|
|
int isBool(int result);
|
|
elem *toElem(IRState *irs);
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
void toMangleBuffer(OutBuffer *buf);
|
|
Expression *optimize(int result, bool keepLvalue = false);
|
|
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
|
MATCH implicitConvTo(Type *t);
|
|
Expression *castTo(Scope *sc, Type *t);
|
|
Expression *inferType(Type *t, int flag = 0, Scope *sc = NULL, TemplateParameters *tparams = NULL);
|
|
|
|
Expression *doInline(InlineDoState *ids);
|
|
Expression *inlineScan(InlineScanState *iss);
|
|
};
|
|
|
|
// scrubReturnValue is running
|
|
#define stageScrub 0x1
|
|
// hasNonConstPointers is running
|
|
#define stageSearchPointers 0x2
|
|
// optimize is running
|
|
#define stageOptimize 0x4
|
|
// apply is running
|
|
#define stageApply 0x8
|
|
//inlineScan is running
|
|
#define stageInlineScan 0x10
|
|
// toCBuffer is running
|
|
#define stageToCBuffer 0x20
|
|
|
|
class StructLiteralExp : public Expression
|
|
{
|
|
public:
|
|
StructDeclaration *sd; // which aggregate this is for
|
|
Expressions *elements; // parallels sd->fields[] with
|
|
// NULL entries for fields to skip
|
|
Type *stype; // final type of result (can be different from sd's type)
|
|
|
|
#if IN_DMD
|
|
Symbol *sinit; // if this is a defaultInitLiteral, this symbol contains the default initializer
|
|
Symbol *sym; // back end symbol to initialize with literal
|
|
#endif
|
|
size_t soffset; // offset from start of s
|
|
int fillHoles; // fill alignment 'holes' with zero
|
|
bool ownedByCtfe; // true = created in CTFE
|
|
|
|
StructLiteralExp *origin; // pointer to the origin instance of the expression.
|
|
// once a new expression is created, origin is set to 'this'.
|
|
// anytime when an expression copy is created, 'origin' pointer is set to
|
|
// 'origin' pointer value of the original expression.
|
|
|
|
StructLiteralExp *inlinecopy; // those fields need to prevent a infinite recursion when one field of struct initialized with 'this' pointer.
|
|
int stageflags; // anytime when recursive function is calling, 'stageflags' marks with bit flag of
|
|
// current stage and unmarks before return from this function.
|
|
// 'inlinecopy' uses similar 'stageflags' and from multiple evaluation 'doInline'
|
|
// (with infinite recursion) of this expression.
|
|
|
|
StructLiteralExp(Loc loc, StructDeclaration *sd, Expressions *elements, Type *stype = NULL);
|
|
bool equals(RootObject *o);
|
|
Expression *syntaxCopy();
|
|
int apply(apply_fp_t fp, void *param);
|
|
Expression *semantic(Scope *sc);
|
|
Expression *fill(bool ctorinit);
|
|
Expression *getField(Type *type, unsigned offset);
|
|
int getFieldIndex(Type *type, unsigned offset);
|
|
elem *toElem(IRState *irs);
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
void toMangleBuffer(OutBuffer *buf);
|
|
Expression *optimize(int result, bool keepLvalue = false);
|
|
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
|
#if IN_LLVM
|
|
// With the introduction of pointers returned from CTFE, struct literals can
|
|
// now contain pointers to themselves. While in toElem, contains a pointer
|
|
// to the memory used to build the literal for resolving such references.
|
|
llvm::Value* inProgressMemory;
|
|
|
|
llvm::Constant *toConstElem(IRState *irs);
|
|
// A global variable for taking the address of this struct literal constant,
|
|
// if it already exists. Used to resolve self-references.
|
|
llvm::GlobalVariable *globalVar;
|
|
|
|
/// Set if this is really the result of a struct .init access and should be
|
|
/// resolved codegen'd as an access to the given SymbolDeclaration.
|
|
// LDC_FIXME: Figure out whether this, i.e. imitating the DMD behavior, is
|
|
// really the best way to fix the nested struct constant folding issue.
|
|
SymbolDeclaration *sinit;
|
|
#else
|
|
dt_t **toDt(dt_t **pdt);
|
|
Symbol *toSymbol();
|
|
#endif
|
|
MATCH implicitConvTo(Type *t);
|
|
Expression *castTo(Scope *sc, Type *t);
|
|
|
|
int inlineCost3(InlineCostState *ics);
|
|
Expression *doInline(InlineDoState *ids);
|
|
Expression *inlineScan(InlineScanState *iss);
|
|
};
|
|
|
|
class DotIdExp;
|
|
DotIdExp *typeDotIdExp(Loc loc, Type *type, Identifier *ident);
|
|
|
|
class TypeExp : public Expression
|
|
{
|
|
public:
|
|
TypeExp(Loc loc, Type *type);
|
|
Expression *syntaxCopy();
|
|
Expression *semantic(Scope *sc);
|
|
int rvalue();
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
Expression *optimize(int result, bool keepLvalue = false);
|
|
elem *toElem(IRState *irs);
|
|
};
|
|
|
|
class ScopeExp : public Expression
|
|
{
|
|
public:
|
|
ScopeDsymbol *sds;
|
|
|
|
ScopeExp(Loc loc, ScopeDsymbol *sds);
|
|
Expression *syntaxCopy();
|
|
Expression *semantic(Scope *sc);
|
|
elem *toElem(IRState *irs);
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
};
|
|
|
|
class TemplateExp : public Expression
|
|
{
|
|
public:
|
|
TemplateDeclaration *td;
|
|
FuncDeclaration *fd;
|
|
|
|
TemplateExp(Loc loc, TemplateDeclaration *td, FuncDeclaration *fd = NULL);
|
|
int rvalue();
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
int isLvalue();
|
|
Expression *toLvalue(Scope *sc, Expression *e);
|
|
};
|
|
|
|
class NewExp : public Expression
|
|
{
|
|
public:
|
|
/* thisexp.new(newargs) newtype(arguments)
|
|
*/
|
|
Expression *thisexp; // if !NULL, 'this' for class being allocated
|
|
Expressions *newargs; // Array of Expression's to call new operator
|
|
Type *newtype;
|
|
Expressions *arguments; // Array of Expression's
|
|
|
|
CtorDeclaration *member; // constructor function
|
|
NewDeclaration *allocator; // allocator function
|
|
int onstack; // allocate on stack
|
|
|
|
NewExp(Loc loc, Expression *thisexp, Expressions *newargs,
|
|
Type *newtype, Expressions *arguments);
|
|
Expression *syntaxCopy();
|
|
int apply(apply_fp_t fp, void *param);
|
|
Expression *semantic(Scope *sc);
|
|
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
|
Expression *optimize(int result, bool keepLvalue = false);
|
|
MATCH implicitConvTo(Type *t);
|
|
elem *toElem(IRState *irs);
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
|
|
//int inlineCost3(InlineCostState *ics);
|
|
Expression *doInline(InlineDoState *ids);
|
|
//Expression *inlineScan(InlineScanState *iss);
|
|
};
|
|
|
|
class NewAnonClassExp : public Expression
|
|
{
|
|
public:
|
|
/* thisexp.new(newargs) class baseclasses { } (arguments)
|
|
*/
|
|
Expression *thisexp; // if !NULL, 'this' for class being allocated
|
|
Expressions *newargs; // Array of Expression's to call new operator
|
|
ClassDeclaration *cd; // class being instantiated
|
|
Expressions *arguments; // Array of Expression's to call class constructor
|
|
|
|
NewAnonClassExp(Loc loc, Expression *thisexp, Expressions *newargs,
|
|
ClassDeclaration *cd, Expressions *arguments);
|
|
Expression *syntaxCopy();
|
|
int apply(apply_fp_t fp, void *param);
|
|
Expression *semantic(Scope *sc);
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
};
|
|
|
|
#if DMDV2
|
|
class SymbolExp : public Expression
|
|
{
|
|
public:
|
|
Declaration *var;
|
|
bool hasOverloads;
|
|
|
|
SymbolExp(Loc loc, TOK op, int size, Declaration *var, bool hasOverloads);
|
|
|
|
elem *toElem(IRState *irs);
|
|
};
|
|
#endif
|
|
|
|
// Offset from symbol
|
|
|
|
class SymOffExp : public SymbolExp
|
|
{
|
|
public:
|
|
unsigned offset;
|
|
|
|
SymOffExp(Loc loc, Declaration *var, unsigned offset, bool hasOverloads = false);
|
|
Expression *semantic(Scope *sc);
|
|
Expression *optimize(int result, bool keepLvalue = false);
|
|
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
|
void checkEscape();
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
int isConst();
|
|
int isBool(int result);
|
|
Expression *doInline(InlineDoState *ids);
|
|
MATCH implicitConvTo(Type *t);
|
|
Expression *castTo(Scope *sc, Type *t);
|
|
|
|
#if IN_LLVM
|
|
DValue* toElem(IRState* irs);
|
|
llvm::Constant* toConstElem(IRState* irs);
|
|
#else
|
|
dt_t **toDt(dt_t **pdt);
|
|
#endif
|
|
};
|
|
|
|
// Variable
|
|
|
|
class VarExp : public SymbolExp
|
|
{
|
|
public:
|
|
VarExp(Loc loc, Declaration *var, bool hasOverloads = false);
|
|
bool equals(RootObject *o);
|
|
Expression *semantic(Scope *sc);
|
|
Expression *optimize(int result, bool keepLvalue = false);
|
|
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
|
void dump(int indent);
|
|
char *toChars();
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
void checkEscape();
|
|
void checkEscapeRef();
|
|
int checkModifiable(Scope *sc, int flag);
|
|
int isLvalue();
|
|
Expression *toLvalue(Scope *sc, Expression *e);
|
|
Expression *modifiableLvalue(Scope *sc, Expression *e);
|
|
#if IN_LLVM
|
|
DValue* toElem(IRState* irs);
|
|
llvm::Constant *toConstElem(IRState *irs);
|
|
void cacheLvalue(IRState* irs);
|
|
#else
|
|
dt_t **toDt(dt_t **pdt);
|
|
#endif
|
|
|
|
int inlineCost3(InlineCostState *ics);
|
|
Expression *doInline(InlineDoState *ids);
|
|
//Expression *inlineScan(InlineScanState *iss);
|
|
};
|
|
|
|
#if DMDV2
|
|
// Overload Set
|
|
|
|
class OverExp : public Expression
|
|
{
|
|
public:
|
|
OverloadSet *vars;
|
|
|
|
OverExp(Loc loc, OverloadSet *s);
|
|
int isLvalue();
|
|
Expression *toLvalue(Scope *sc, Expression *e);
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
};
|
|
#endif
|
|
|
|
// Function/Delegate literal
|
|
|
|
class FuncExp : public Expression
|
|
{
|
|
public:
|
|
FuncLiteralDeclaration *fd;
|
|
TemplateDeclaration *td;
|
|
TOK tok;
|
|
|
|
FuncExp(Loc loc, FuncLiteralDeclaration *fd, TemplateDeclaration *td = NULL);
|
|
void genIdent(Scope *sc);
|
|
Expression *syntaxCopy();
|
|
Expression *semantic(Scope *sc);
|
|
Expression *semantic(Scope *sc, Expressions *arguments);
|
|
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
|
Expression *implicitCastTo(Scope *sc, Type *t);
|
|
MATCH implicitConvTo(Type *t);
|
|
Expression *castTo(Scope *sc, Type *t);
|
|
Expression *inferType(Type *t, int flag = 0, Scope *sc = NULL, TemplateParameters *tparams = NULL);
|
|
char *toChars();
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
elem *toElem(IRState *irs);
|
|
#if IN_LLVM
|
|
llvm::Constant *toConstElem(IRState *irs);
|
|
#else
|
|
dt_t **toDt(dt_t **pdt);
|
|
#endif
|
|
|
|
int inlineCost3(InlineCostState *ics);
|
|
//Expression *doInline(InlineDoState *ids);
|
|
//Expression *inlineScan(InlineScanState *iss);
|
|
};
|
|
|
|
// Declaration of a symbol
|
|
|
|
class DeclarationExp : public Expression
|
|
{
|
|
public:
|
|
Dsymbol *declaration;
|
|
|
|
DeclarationExp(Loc loc, Dsymbol *declaration);
|
|
Expression *syntaxCopy();
|
|
Expression *semantic(Scope *sc);
|
|
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
elem *toElem(IRState *irs);
|
|
|
|
int inlineCost3(InlineCostState *ics);
|
|
Expression *doInline(InlineDoState *ids);
|
|
Expression *inlineScan(InlineScanState *iss);
|
|
};
|
|
|
|
class TypeidExp : public Expression
|
|
{
|
|
public:
|
|
RootObject *obj;
|
|
|
|
TypeidExp(Loc loc, RootObject *obj);
|
|
Expression *syntaxCopy();
|
|
Expression *semantic(Scope *sc);
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
};
|
|
|
|
#if DMDV2
|
|
class TraitsExp : public Expression
|
|
{
|
|
public:
|
|
Identifier *ident;
|
|
Objects *args;
|
|
|
|
TraitsExp(Loc loc, Identifier *ident, Objects *args);
|
|
Expression *syntaxCopy();
|
|
Expression *semantic(Scope *sc);
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
};
|
|
#endif
|
|
|
|
class HaltExp : public Expression
|
|
{
|
|
public:
|
|
HaltExp(Loc loc);
|
|
Expression *semantic(Scope *sc);
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
|
|
elem *toElem(IRState *irs);
|
|
};
|
|
|
|
class IsExp : public Expression
|
|
{
|
|
public:
|
|
/* is(targ id tok tspec)
|
|
* is(targ id == tok2)
|
|
*/
|
|
Type *targ;
|
|
Identifier *id; // can be NULL
|
|
TOK tok; // ':' or '=='
|
|
Type *tspec; // can be NULL
|
|
TOK tok2; // 'struct', 'union', 'typedef', etc.
|
|
TemplateParameters *parameters;
|
|
|
|
IsExp(Loc loc, Type *targ, Identifier *id, TOK tok, Type *tspec,
|
|
TOK tok2, TemplateParameters *parameters);
|
|
Expression *syntaxCopy();
|
|
Expression *semantic(Scope *sc);
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
};
|
|
|
|
/****************************************************************/
|
|
|
|
class UnaExp : public Expression
|
|
{
|
|
public:
|
|
Expression *e1;
|
|
Type *att1; // Save alias this type to detect recursion
|
|
|
|
UnaExp(Loc loc, TOK op, int size, Expression *e1);
|
|
Expression *syntaxCopy();
|
|
int apply(apply_fp_t fp, void *param);
|
|
Expression *semantic(Scope *sc);
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
Expression *optimize(int result, bool keepLvalue = false);
|
|
void dump(int indent);
|
|
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
|
Expression *resolveLoc(Loc loc, Scope *sc);
|
|
|
|
Expression *doInline(InlineDoState *ids);
|
|
Expression *inlineScan(InlineScanState *iss);
|
|
|
|
virtual Expression *op_overload(Scope *sc);
|
|
};
|
|
|
|
typedef Expression *(*fp_t)(Type *, Expression *, Expression *);
|
|
typedef int (*fp2_t)(Loc loc, TOK, Expression *, Expression *);
|
|
|
|
class BinExp : public Expression
|
|
{
|
|
public:
|
|
Expression *e1;
|
|
Expression *e2;
|
|
|
|
Type *att1; // Save alias this type to detect recursion
|
|
Type *att2; // Save alias this type to detect recursion
|
|
|
|
BinExp(Loc loc, TOK op, int size, Expression *e1, Expression *e2);
|
|
Expression *syntaxCopy();
|
|
int apply(apply_fp_t fp, void *param);
|
|
Expression *semantic(Scope *sc);
|
|
Expression *semanticp(Scope *sc);
|
|
Expression *checkComplexOpAssign(Scope *sc);
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
Expression *scaleFactor(Scope *sc);
|
|
Expression *typeCombine(Scope *sc);
|
|
Expression *optimize(int result, bool keepLvalue = false);
|
|
int isunsigned();
|
|
Expression *incompatibleTypes();
|
|
void dump(int indent);
|
|
|
|
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
|
Expression *interpretCommon(InterState *istate, CtfeGoal goal, fp_t fp);
|
|
Expression *interpretCompareCommon(InterState *istate, CtfeGoal goal, fp2_t fp);
|
|
Expression *interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_t fp, int post = 0);
|
|
Expression *interpretFourPointerRelation(InterState *istate, CtfeGoal goal);
|
|
virtual Expression *arrayOp(Scope *sc);
|
|
|
|
Expression *doInline(InlineDoState *ids);
|
|
Expression *inlineScan(InlineScanState *iss);
|
|
|
|
Expression *op_overload(Scope *sc);
|
|
Expression *compare_overload(Scope *sc, Identifier *id);
|
|
Expression *reorderSettingAAElem(Scope *sc);
|
|
|
|
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
|
|
Expression *buildArrayLoop(Parameters *fparams);
|
|
|
|
#if IN_DMD
|
|
elem *toElemBin(IRState *irs, int op);
|
|
#endif
|
|
};
|
|
|
|
class BinAssignExp : public BinExp
|
|
{
|
|
public:
|
|
BinAssignExp(Loc loc, TOK op, int size, Expression *e1, Expression *e2)
|
|
: BinExp(loc, op, size, e1, e2)
|
|
{
|
|
}
|
|
|
|
Expression *semantic(Scope *sc);
|
|
Expression *arrayOp(Scope *sc);
|
|
|
|
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
|
|
|
Expression *op_overload(Scope *sc);
|
|
|
|
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
|
|
Expression *buildArrayLoop(Parameters *fparams);
|
|
|
|
int isLvalue();
|
|
Expression *toLvalue(Scope *sc, Expression *ex);
|
|
Expression *modifiableLvalue(Scope *sc, Expression *e);
|
|
};
|
|
|
|
/****************************************************************/
|
|
|
|
class CompileExp : public UnaExp
|
|
{
|
|
public:
|
|
CompileExp(Loc loc, Expression *e);
|
|
Expression *semantic(Scope *sc);
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
};
|
|
|
|
class FileExp : public UnaExp
|
|
{
|
|
public:
|
|
FileExp(Loc loc, Expression *e);
|
|
Expression *semantic(Scope *sc);
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
};
|
|
|
|
class AssertExp : public UnaExp
|
|
{
|
|
public:
|
|
Expression *msg;
|
|
|
|
AssertExp(Loc loc, Expression *e, Expression *msg = NULL);
|
|
Expression *syntaxCopy();
|
|
int apply(apply_fp_t fp, void *param);
|
|
Expression *semantic(Scope *sc);
|
|
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
|
|
Expression *doInline(InlineDoState *ids);
|
|
Expression *inlineScan(InlineScanState *iss);
|
|
|
|
elem *toElem(IRState *irs);
|
|
};
|
|
|
|
class DotIdExp : public UnaExp
|
|
{
|
|
public:
|
|
Identifier *ident;
|
|
|
|
DotIdExp(Loc loc, Expression *e, Identifier *ident);
|
|
Expression *semantic(Scope *sc);
|
|
Expression *semanticX(Scope *sc);
|
|
Expression *semanticY(Scope *sc, int flag);
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
void dump(int i);
|
|
};
|
|
|
|
class DotTemplateExp : public UnaExp
|
|
{
|
|
public:
|
|
TemplateDeclaration *td;
|
|
|
|
DotTemplateExp(Loc loc, Expression *e, TemplateDeclaration *td);
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
};
|
|
|
|
class DotVarExp : public UnaExp
|
|
{
|
|
public:
|
|
Declaration *var;
|
|
bool hasOverloads;
|
|
|
|
DotVarExp(Loc loc, Expression *e, Declaration *var, bool hasOverloads = false);
|
|
Expression *semantic(Scope *sc);
|
|
int checkModifiable(Scope *sc, int flag);
|
|
int isLvalue();
|
|
Expression *toLvalue(Scope *sc, Expression *e);
|
|
Expression *modifiableLvalue(Scope *sc, Expression *e);
|
|
Expression *optimize(int result, bool keepLvalue = false);
|
|
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
void dump(int indent);
|
|
elem *toElem(IRState *irs);
|
|
|
|
#if IN_LLVM
|
|
void cacheLvalue(IRState* irs);
|
|
#endif
|
|
};
|
|
|
|
class DotTemplateInstanceExp : public UnaExp
|
|
{
|
|
public:
|
|
TemplateInstance *ti;
|
|
|
|
DotTemplateInstanceExp(Loc loc, Expression *e, Identifier *name, Objects *tiargs);
|
|
Expression *syntaxCopy();
|
|
bool findTempDecl(Scope *sc);
|
|
Expression *semantic(Scope *sc);
|
|
Expression *semanticY(Scope *sc, int flag);
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
void dump(int indent);
|
|
};
|
|
|
|
class DelegateExp : public UnaExp
|
|
{
|
|
public:
|
|
FuncDeclaration *func;
|
|
bool hasOverloads;
|
|
|
|
DelegateExp(Loc loc, Expression *e, FuncDeclaration *func, bool hasOverloads = false);
|
|
Expression *semantic(Scope *sc);
|
|
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
|
MATCH implicitConvTo(Type *t);
|
|
Expression *castTo(Scope *sc, Type *t);
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
void dump(int indent);
|
|
|
|
int inlineCost3(InlineCostState *ics);
|
|
elem *toElem(IRState *irs);
|
|
};
|
|
|
|
class DotTypeExp : public UnaExp
|
|
{
|
|
public:
|
|
Dsymbol *sym; // symbol that represents a type
|
|
|
|
DotTypeExp(Loc loc, Expression *e, Dsymbol *sym);
|
|
Expression *semantic(Scope *sc);
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
elem *toElem(IRState *irs);
|
|
};
|
|
|
|
class CallExp : public UnaExp
|
|
{
|
|
public:
|
|
Expressions *arguments; // function arguments
|
|
FuncDeclaration *f; // symbol to call
|
|
|
|
CallExp(Loc loc, Expression *e, Expressions *exps);
|
|
CallExp(Loc loc, Expression *e);
|
|
CallExp(Loc loc, Expression *e, Expression *earg1);
|
|
CallExp(Loc loc, Expression *e, Expression *earg1, Expression *earg2);
|
|
|
|
Expression *syntaxCopy();
|
|
int apply(apply_fp_t fp, void *param);
|
|
Expression *semantic(Scope *sc);
|
|
Expression *optimize(int result, bool keepLvalue = false);
|
|
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
void dump(int indent);
|
|
elem *toElem(IRState *irs);
|
|
int isLvalue();
|
|
Expression *toLvalue(Scope *sc, Expression *e);
|
|
Expression *addDtorHook(Scope *sc);
|
|
MATCH implicitConvTo(Type *t);
|
|
|
|
int inlineCost3(InlineCostState *ics);
|
|
Expression *doInline(InlineDoState *ids);
|
|
Expression *inlineScan(InlineScanState *iss);
|
|
|
|
#if IN_LLVM
|
|
void cacheLvalue(IRState* p);
|
|
#endif
|
|
};
|
|
|
|
class AddrExp : public UnaExp
|
|
{
|
|
public:
|
|
AddrExp(Loc loc, Expression *e);
|
|
Expression *semantic(Scope *sc);
|
|
void checkEscape();
|
|
elem *toElem(IRState *irs);
|
|
MATCH implicitConvTo(Type *t);
|
|
Expression *castTo(Scope *sc, Type *t);
|
|
Expression *optimize(int result, bool keepLvalue = false);
|
|
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
|
#if IN_LLVM
|
|
llvm::Constant *toConstElem(IRState *irs);
|
|
#else
|
|
dt_t **toDt(dt_t **pdt);
|
|
#endif
|
|
};
|
|
|
|
class PtrExp : public UnaExp
|
|
{
|
|
public:
|
|
PtrExp(Loc loc, Expression *e);
|
|
PtrExp(Loc loc, Expression *e, Type *t);
|
|
Expression *semantic(Scope *sc);
|
|
void checkEscapeRef();
|
|
int checkModifiable(Scope *sc, int flag);
|
|
int isLvalue();
|
|
Expression *toLvalue(Scope *sc, Expression *e);
|
|
Expression *modifiableLvalue(Scope *sc, Expression *e);
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
elem *toElem(IRState *irs);
|
|
Expression *optimize(int result, bool keepLvalue = false);
|
|
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
|
|
|
// For operator overloading
|
|
Identifier *opId();
|
|
|
|
#if IN_LLVM
|
|
void cacheLvalue(IRState* irs);
|
|
#endif
|
|
};
|
|
|
|
class NegExp : public UnaExp
|
|
{
|
|
public:
|
|
NegExp(Loc loc, Expression *e);
|
|
Expression *semantic(Scope *sc);
|
|
Expression *optimize(int result, bool keepLvalue = false);
|
|
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
|
|
Expression *buildArrayLoop(Parameters *fparams);
|
|
IntRange getIntRange();
|
|
|
|
// For operator overloading
|
|
Identifier *opId();
|
|
|
|
elem *toElem(IRState *irs);
|
|
};
|
|
|
|
class UAddExp : public UnaExp
|
|
{
|
|
public:
|
|
UAddExp(Loc loc, Expression *e);
|
|
Expression *semantic(Scope *sc);
|
|
|
|
// For operator overloading
|
|
Identifier *opId();
|
|
};
|
|
|
|
class ComExp : public UnaExp
|
|
{
|
|
public:
|
|
ComExp(Loc loc, Expression *e);
|
|
Expression *semantic(Scope *sc);
|
|
Expression *optimize(int result, bool keepLvalue = false);
|
|
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
|
|
Expression *buildArrayLoop(Parameters *fparams);
|
|
IntRange getIntRange();
|
|
|
|
// For operator overloading
|
|
Identifier *opId();
|
|
|
|
elem *toElem(IRState *irs);
|
|
};
|
|
|
|
class NotExp : public UnaExp
|
|
{
|
|
public:
|
|
NotExp(Loc loc, Expression *e);
|
|
Expression *semantic(Scope *sc);
|
|
Expression *optimize(int result, bool keepLvalue = false);
|
|
int isBit();
|
|
elem *toElem(IRState *irs);
|
|
};
|
|
|
|
class BoolExp : public UnaExp
|
|
{
|
|
public:
|
|
BoolExp(Loc loc, Expression *e, Type *type);
|
|
Expression *semantic(Scope *sc);
|
|
Expression *optimize(int result, bool keepLvalue = false);
|
|
int isBit();
|
|
elem *toElem(IRState *irs);
|
|
};
|
|
|
|
class DeleteExp : public UnaExp
|
|
{
|
|
public:
|
|
DeleteExp(Loc loc, Expression *e);
|
|
Expression *semantic(Scope *sc);
|
|
Expression *checkToBoolean(Scope *sc);
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
elem *toElem(IRState *irs);
|
|
};
|
|
|
|
class CastExp : public UnaExp
|
|
{
|
|
public:
|
|
// Possible to cast to one type while painting to another type
|
|
Type *to; // type to cast to
|
|
unsigned mod; // MODxxxxx
|
|
|
|
CastExp(Loc loc, Expression *e, Type *t);
|
|
CastExp(Loc loc, Expression *e, unsigned mod);
|
|
Expression *syntaxCopy();
|
|
Expression *semantic(Scope *sc);
|
|
MATCH implicitConvTo(Type *t);
|
|
IntRange getIntRange();
|
|
Expression *optimize(int result, bool keepLvalue = false);
|
|
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
|
void checkEscape();
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
|
|
Expression *buildArrayLoop(Parameters *fparams);
|
|
elem *toElem(IRState *irs);
|
|
|
|
// For operator overloading
|
|
Identifier *opId();
|
|
Expression *op_overload(Scope *sc);
|
|
|
|
#if IN_LLVM
|
|
llvm::Constant *toConstElem(IRState *irs);
|
|
#else
|
|
dt_t **toDt(dt_t **pdt);
|
|
#endif
|
|
};
|
|
|
|
class VectorExp : public UnaExp
|
|
{
|
|
public:
|
|
TypeVector *to; // the target vector type before semantic()
|
|
unsigned dim; // number of elements in the vector
|
|
|
|
VectorExp(Loc loc, Expression *e, Type *t);
|
|
Expression *syntaxCopy();
|
|
Expression *semantic(Scope *sc);
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
elem *toElem(IRState *irs);
|
|
#if IN_DMD
|
|
dt_t **toDt(dt_t **pdt);
|
|
#endif
|
|
};
|
|
|
|
class SliceExp : public UnaExp
|
|
{
|
|
public:
|
|
Expression *upr; // NULL if implicit 0
|
|
Expression *lwr; // NULL if implicit [length - 1]
|
|
VarDeclaration *lengthVar;
|
|
|
|
SliceExp(Loc loc, Expression *e1, Expression *lwr, Expression *upr);
|
|
Expression *syntaxCopy();
|
|
int apply(apply_fp_t fp, void *param);
|
|
Expression *semantic(Scope *sc);
|
|
void checkEscape();
|
|
void checkEscapeRef();
|
|
int checkModifiable(Scope *sc, int flag);
|
|
int isLvalue();
|
|
Expression *toLvalue(Scope *sc, Expression *e);
|
|
Expression *modifiableLvalue(Scope *sc, Expression *e);
|
|
int isBool(int result);
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
Type *toStaticArrayType();
|
|
MATCH implicitConvTo(Type *t);
|
|
Expression *castTo(Scope *sc, Type *t);
|
|
Expression *optimize(int result, bool keepLvalue = false);
|
|
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
|
void dump(int indent);
|
|
elem *toElem(IRState *irs);
|
|
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
|
|
Expression *buildArrayLoop(Parameters *fparams);
|
|
|
|
Expression *doInline(InlineDoState *ids);
|
|
Expression *inlineScan(InlineScanState *iss);
|
|
};
|
|
|
|
class ArrayLengthExp : public UnaExp
|
|
{
|
|
public:
|
|
ArrayLengthExp(Loc loc, Expression *e1);
|
|
Expression *semantic(Scope *sc);
|
|
Expression *optimize(int result, bool keepLvalue = false);
|
|
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
elem *toElem(IRState *irs);
|
|
|
|
static Expression *rewriteOpAssign(BinExp *exp);
|
|
};
|
|
|
|
// e1[a0,a1,a2,a3,...]
|
|
|
|
class ArrayExp : public UnaExp
|
|
{
|
|
public:
|
|
Expressions *arguments; // Array of Expression's
|
|
size_t currentDimension; // for opDollar
|
|
VarDeclaration *lengthVar;
|
|
|
|
ArrayExp(Loc loc, Expression *e1, Expressions *arguments);
|
|
Expression *syntaxCopy();
|
|
int apply(apply_fp_t fp, void *param);
|
|
Expression *semantic(Scope *sc);
|
|
int isLvalue();
|
|
Expression *toLvalue(Scope *sc, Expression *e);
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
|
|
// For operator overloading
|
|
Identifier *opId();
|
|
Expression *op_overload(Scope *sc);
|
|
|
|
Expression *doInline(InlineDoState *ids);
|
|
Expression *inlineScan(InlineScanState *iss);
|
|
};
|
|
|
|
/****************************************************************/
|
|
|
|
class DotExp : public BinExp
|
|
{
|
|
public:
|
|
DotExp(Loc loc, Expression *e1, Expression *e2);
|
|
Expression *semantic(Scope *sc);
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
};
|
|
|
|
class CommaExp : public BinExp
|
|
{
|
|
public:
|
|
CommaExp(Loc loc, Expression *e1, Expression *e2);
|
|
Expression *semantic(Scope *sc);
|
|
void checkEscape();
|
|
void checkEscapeRef();
|
|
int checkModifiable(Scope *sc, int flag);
|
|
IntRange getIntRange();
|
|
int isLvalue();
|
|
Expression *toLvalue(Scope *sc, Expression *e);
|
|
Expression *modifiableLvalue(Scope *sc, Expression *e);
|
|
int isBool(int result);
|
|
MATCH implicitConvTo(Type *t);
|
|
Expression *addDtorHook(Scope *sc);
|
|
Expression *castTo(Scope *sc, Type *t);
|
|
Expression *optimize(int result, bool keepLvalue = false);
|
|
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
|
elem *toElem(IRState *irs);
|
|
|
|
#if IN_LLVM
|
|
void cacheLvalue(IRState* irs);
|
|
#endif
|
|
};
|
|
|
|
class IndexExp : public BinExp
|
|
{
|
|
public:
|
|
VarDeclaration *lengthVar;
|
|
int modifiable;
|
|
bool skipboundscheck;
|
|
|
|
IndexExp(Loc loc, Expression *e1, Expression *e2);
|
|
Expression *syntaxCopy();
|
|
Expression *semantic(Scope *sc);
|
|
int checkModifiable(Scope *sc, int flag);
|
|
int isLvalue();
|
|
Expression *toLvalue(Scope *sc, Expression *e);
|
|
Expression *modifiableLvalue(Scope *sc, Expression *e);
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
Expression *optimize(int result, bool keepLvalue = false);
|
|
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
|
Expression *doInline(InlineDoState *ids);
|
|
|
|
elem *toElem(IRState *irs);
|
|
|
|
#if IN_LLVM
|
|
void cacheLvalue(IRState* irs);
|
|
#endif
|
|
};
|
|
|
|
/* For both i++ and i--
|
|
*/
|
|
class PostExp : public BinExp
|
|
{
|
|
public:
|
|
PostExp(TOK op, Loc loc, Expression *e);
|
|
Expression *semantic(Scope *sc);
|
|
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
Identifier *opId(); // For operator overloading
|
|
elem *toElem(IRState *irs);
|
|
};
|
|
|
|
/* For both ++i and --i
|
|
*/
|
|
class PreExp : public UnaExp
|
|
{
|
|
public:
|
|
PreExp(TOK op, Loc loc, Expression *e);
|
|
Expression *semantic(Scope *sc);
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
};
|
|
|
|
class AssignExp : public BinExp
|
|
{
|
|
public:
|
|
int ismemset; // !=0 if setting the contents of an array
|
|
|
|
AssignExp(Loc loc, Expression *e1, Expression *e2);
|
|
Expression *semantic(Scope *sc);
|
|
Expression *checkToBoolean(Scope *sc);
|
|
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
|
Identifier *opId(); // For operator overloading
|
|
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
|
|
Expression *buildArrayLoop(Parameters *fparams);
|
|
elem *toElem(IRState *irs);
|
|
|
|
#if IN_LLVM
|
|
virtual AssignExp* isAssignExp() { return this; }
|
|
#endif
|
|
};
|
|
|
|
class ConstructExp : public AssignExp
|
|
{
|
|
public:
|
|
ConstructExp(Loc loc, Expression *e1, Expression *e2);
|
|
};
|
|
|
|
#define ASSIGNEXP(op) \
|
|
class op##AssignExp : public BinAssignExp \
|
|
{ \
|
|
public: \
|
|
op##AssignExp(Loc loc, Expression *e1, Expression *e2); \
|
|
S(Expression *semantic(Scope *sc);) \
|
|
\
|
|
Identifier *opId(); /* For operator overloading */ \
|
|
\
|
|
elem *toElem(IRState *irs); \
|
|
};
|
|
|
|
#define X(a) a
|
|
#define S(a)
|
|
ASSIGNEXP(Add)
|
|
ASSIGNEXP(Min)
|
|
ASSIGNEXP(Mul)
|
|
ASSIGNEXP(Div)
|
|
ASSIGNEXP(Mod)
|
|
ASSIGNEXP(And)
|
|
ASSIGNEXP(Or)
|
|
ASSIGNEXP(Xor)
|
|
#undef S
|
|
|
|
#if DMDV2
|
|
#define S(a) a
|
|
ASSIGNEXP(Pow)
|
|
#undef S
|
|
#endif
|
|
|
|
#undef S
|
|
#undef X
|
|
|
|
#define X(a)
|
|
|
|
#define S(a)
|
|
ASSIGNEXP(Shl)
|
|
ASSIGNEXP(Shr)
|
|
ASSIGNEXP(Ushr)
|
|
#undef S
|
|
|
|
#define S(a) a
|
|
ASSIGNEXP(Cat)
|
|
#undef S
|
|
|
|
#undef X
|
|
#undef ASSIGNEXP
|
|
|
|
class AddExp : public BinExp
|
|
{
|
|
public:
|
|
AddExp(Loc loc, Expression *e1, Expression *e2);
|
|
Expression *semantic(Scope *sc);
|
|
Expression *optimize(int result, bool keepLvalue = false);
|
|
IntRange getIntRange();
|
|
|
|
// For operator overloading
|
|
int isCommutative();
|
|
Identifier *opId();
|
|
Identifier *opId_r();
|
|
|
|
elem *toElem(IRState *irs);
|
|
|
|
#if IN_LLVM
|
|
llvm::Constant *toConstElem(IRState* p);
|
|
#endif
|
|
};
|
|
|
|
class MinExp : public BinExp
|
|
{
|
|
public:
|
|
MinExp(Loc loc, Expression *e1, Expression *e2);
|
|
Expression *semantic(Scope *sc);
|
|
Expression *optimize(int result, bool keepLvalue = false);
|
|
IntRange getIntRange();
|
|
|
|
// For operator overloading
|
|
Identifier *opId();
|
|
Identifier *opId_r();
|
|
|
|
elem *toElem(IRState *irs);
|
|
|
|
#if IN_LLVM
|
|
llvm::Constant *toConstElem(IRState* p);
|
|
#endif
|
|
};
|
|
|
|
class CatExp : public BinExp
|
|
{
|
|
public:
|
|
CatExp(Loc loc, Expression *e1, Expression *e2);
|
|
Expression *semantic(Scope *sc);
|
|
Expression *optimize(int result, bool keepLvalue = false);
|
|
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
|
|
|
// For operator overloading
|
|
Identifier *opId();
|
|
Identifier *opId_r();
|
|
|
|
elem *toElem(IRState *irs);
|
|
};
|
|
|
|
class MulExp : public BinExp
|
|
{
|
|
public:
|
|
MulExp(Loc loc, Expression *e1, Expression *e2);
|
|
Expression *semantic(Scope *sc);
|
|
Expression *optimize(int result, bool keepLvalue = false);
|
|
IntRange getIntRange();
|
|
|
|
// For operator overloading
|
|
int isCommutative();
|
|
Identifier *opId();
|
|
Identifier *opId_r();
|
|
|
|
elem *toElem(IRState *irs);
|
|
};
|
|
|
|
class DivExp : public BinExp
|
|
{
|
|
public:
|
|
DivExp(Loc loc, Expression *e1, Expression *e2);
|
|
Expression *semantic(Scope *sc);
|
|
Expression *optimize(int result, bool keepLvalue = false);
|
|
IntRange getIntRange();
|
|
|
|
// For operator overloading
|
|
Identifier *opId();
|
|
Identifier *opId_r();
|
|
|
|
elem *toElem(IRState *irs);
|
|
};
|
|
|
|
class ModExp : public BinExp
|
|
{
|
|
public:
|
|
ModExp(Loc loc, Expression *e1, Expression *e2);
|
|
Expression *semantic(Scope *sc);
|
|
Expression *optimize(int result, bool keepLvalue = false);
|
|
IntRange getIntRange();
|
|
|
|
// For operator overloading
|
|
Identifier *opId();
|
|
Identifier *opId_r();
|
|
|
|
elem *toElem(IRState *irs);
|
|
};
|
|
|
|
#if DMDV2
|
|
class PowExp : public BinExp
|
|
{
|
|
public:
|
|
PowExp(Loc loc, Expression *e1, Expression *e2);
|
|
Expression *semantic(Scope *sc);
|
|
Expression *optimize(int result, bool keepLvalue = false);
|
|
|
|
// For operator overloading
|
|
Identifier *opId();
|
|
Identifier *opId_r();
|
|
|
|
elem *toElem(IRState *irs);
|
|
};
|
|
#endif
|
|
|
|
class ShlExp : public BinExp
|
|
{
|
|
public:
|
|
ShlExp(Loc loc, Expression *e1, Expression *e2);
|
|
Expression *semantic(Scope *sc);
|
|
Expression *optimize(int result, bool keepLvalue = false);
|
|
IntRange getIntRange();
|
|
|
|
// For operator overloading
|
|
Identifier *opId();
|
|
Identifier *opId_r();
|
|
|
|
elem *toElem(IRState *irs);
|
|
};
|
|
|
|
class ShrExp : public BinExp
|
|
{
|
|
public:
|
|
ShrExp(Loc loc, Expression *e1, Expression *e2);
|
|
Expression *semantic(Scope *sc);
|
|
Expression *optimize(int result, bool keepLvalue = false);
|
|
IntRange getIntRange();
|
|
|
|
// For operator overloading
|
|
Identifier *opId();
|
|
Identifier *opId_r();
|
|
|
|
elem *toElem(IRState *irs);
|
|
};
|
|
|
|
class UshrExp : public BinExp
|
|
{
|
|
public:
|
|
UshrExp(Loc loc, Expression *e1, Expression *e2);
|
|
Expression *semantic(Scope *sc);
|
|
Expression *optimize(int result, bool keepLvalue = false);
|
|
IntRange getIntRange();
|
|
|
|
// For operator overloading
|
|
Identifier *opId();
|
|
Identifier *opId_r();
|
|
|
|
elem *toElem(IRState *irs);
|
|
};
|
|
|
|
class AndExp : public BinExp
|
|
{
|
|
public:
|
|
AndExp(Loc loc, Expression *e1, Expression *e2);
|
|
Expression *semantic(Scope *sc);
|
|
Expression *optimize(int result, bool keepLvalue = false);
|
|
IntRange getIntRange();
|
|
|
|
// For operator overloading
|
|
int isCommutative();
|
|
Identifier *opId();
|
|
Identifier *opId_r();
|
|
|
|
elem *toElem(IRState *irs);
|
|
};
|
|
|
|
class OrExp : public BinExp
|
|
{
|
|
public:
|
|
OrExp(Loc loc, Expression *e1, Expression *e2);
|
|
Expression *semantic(Scope *sc);
|
|
Expression *optimize(int result, bool keepLvalue = false);
|
|
MATCH implicitConvTo(Type *t);
|
|
IntRange getIntRange();
|
|
|
|
// For operator overloading
|
|
int isCommutative();
|
|
Identifier *opId();
|
|
Identifier *opId_r();
|
|
|
|
elem *toElem(IRState *irs);
|
|
};
|
|
|
|
class XorExp : public BinExp
|
|
{
|
|
public:
|
|
XorExp(Loc loc, Expression *e1, Expression *e2);
|
|
Expression *semantic(Scope *sc);
|
|
Expression *optimize(int result, bool keepLvalue = false);
|
|
MATCH implicitConvTo(Type *t);
|
|
IntRange getIntRange();
|
|
|
|
// For operator overloading
|
|
int isCommutative();
|
|
Identifier *opId();
|
|
Identifier *opId_r();
|
|
|
|
elem *toElem(IRState *irs);
|
|
};
|
|
|
|
class OrOrExp : public BinExp
|
|
{
|
|
public:
|
|
OrOrExp(Loc loc, Expression *e1, Expression *e2);
|
|
Expression *semantic(Scope *sc);
|
|
Expression *checkToBoolean(Scope *sc);
|
|
int isBit();
|
|
Expression *optimize(int result, bool keepLvalue = false);
|
|
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
|
elem *toElem(IRState *irs);
|
|
};
|
|
|
|
class AndAndExp : public BinExp
|
|
{
|
|
public:
|
|
AndAndExp(Loc loc, Expression *e1, Expression *e2);
|
|
Expression *semantic(Scope *sc);
|
|
Expression *checkToBoolean(Scope *sc);
|
|
int isBit();
|
|
Expression *optimize(int result, bool keepLvalue = false);
|
|
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
|
elem *toElem(IRState *irs);
|
|
};
|
|
|
|
class CmpExp : public BinExp
|
|
{
|
|
public:
|
|
CmpExp(TOK op, Loc loc, Expression *e1, Expression *e2);
|
|
Expression *semantic(Scope *sc);
|
|
Expression *optimize(int result, bool keepLvalue = false);
|
|
int isBit();
|
|
|
|
// For operator overloading
|
|
int isCommutative();
|
|
Identifier *opId();
|
|
Expression *op_overload(Scope *sc);
|
|
|
|
elem *toElem(IRState *irs);
|
|
};
|
|
|
|
class InExp : public BinExp
|
|
{
|
|
public:
|
|
InExp(Loc loc, Expression *e1, Expression *e2);
|
|
Expression *semantic(Scope *sc);
|
|
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
|
int isBit();
|
|
|
|
// For operator overloading
|
|
Identifier *opId();
|
|
Identifier *opId_r();
|
|
|
|
elem *toElem(IRState *irs);
|
|
};
|
|
|
|
class RemoveExp : public BinExp
|
|
{
|
|
public:
|
|
RemoveExp(Loc loc, Expression *e1, Expression *e2);
|
|
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
elem *toElem(IRState *irs);
|
|
};
|
|
|
|
// == and !=
|
|
|
|
class EqualExp : public BinExp
|
|
{
|
|
public:
|
|
EqualExp(TOK op, Loc loc, Expression *e1, Expression *e2);
|
|
Expression *semantic(Scope *sc);
|
|
Expression *optimize(int result, bool keepLvalue = false);
|
|
int isBit();
|
|
|
|
// For operator overloading
|
|
int isCommutative();
|
|
Identifier *opId();
|
|
Expression *op_overload(Scope *sc);
|
|
|
|
elem *toElem(IRState *irs);
|
|
};
|
|
|
|
// is and !is
|
|
|
|
class IdentityExp : public BinExp
|
|
{
|
|
public:
|
|
IdentityExp(TOK op, Loc loc, Expression *e1, Expression *e2);
|
|
Expression *semantic(Scope *sc);
|
|
int isBit();
|
|
Expression *optimize(int result, bool keepLvalue = false);
|
|
elem *toElem(IRState *irs);
|
|
};
|
|
|
|
/****************************************************************/
|
|
|
|
class CondExp : public BinExp
|
|
{
|
|
public:
|
|
Expression *econd;
|
|
|
|
CondExp(Loc loc, Expression *econd, Expression *e1, Expression *e2);
|
|
Expression *syntaxCopy();
|
|
int apply(apply_fp_t fp, void *param);
|
|
Expression *semantic(Scope *sc);
|
|
Expression *optimize(int result, bool keepLvalue = false);
|
|
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
|
|
void checkEscape();
|
|
void checkEscapeRef();
|
|
int checkModifiable(Scope *sc, int flag);
|
|
int isLvalue();
|
|
Expression *toLvalue(Scope *sc, Expression *e);
|
|
Expression *modifiableLvalue(Scope *sc, Expression *e);
|
|
Expression *checkToBoolean(Scope *sc);
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
MATCH implicitConvTo(Type *t);
|
|
Expression *castTo(Scope *sc, Type *t);
|
|
Expression *inferType(Type *t, int flag = 0, Scope *sc = NULL, TemplateParameters *tparams = NULL);
|
|
|
|
Expression *doInline(InlineDoState *ids);
|
|
Expression *inlineScan(InlineScanState *iss);
|
|
|
|
elem *toElem(IRState *irs);
|
|
};
|
|
|
|
#if DMDV2
|
|
/****************************************************************/
|
|
|
|
class DefaultInitExp : public Expression
|
|
{
|
|
public:
|
|
TOK subop; // which of the derived classes this is
|
|
|
|
DefaultInitExp(Loc loc, TOK subop, int size);
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
};
|
|
|
|
class FileInitExp : public DefaultInitExp
|
|
{
|
|
public:
|
|
FileInitExp(Loc loc);
|
|
Expression *semantic(Scope *sc);
|
|
Expression *resolveLoc(Loc loc, Scope *sc);
|
|
};
|
|
|
|
class LineInitExp : public DefaultInitExp
|
|
{
|
|
public:
|
|
LineInitExp(Loc loc);
|
|
Expression *semantic(Scope *sc);
|
|
Expression *resolveLoc(Loc loc, Scope *sc);
|
|
};
|
|
|
|
class ModuleInitExp : public DefaultInitExp
|
|
{
|
|
public:
|
|
ModuleInitExp(Loc loc);
|
|
Expression *semantic(Scope *sc);
|
|
Expression *resolveLoc(Loc loc, Scope *sc);
|
|
};
|
|
|
|
class FuncInitExp : public DefaultInitExp
|
|
{
|
|
public:
|
|
FuncInitExp(Loc loc);
|
|
Expression *semantic(Scope *sc);
|
|
Expression *resolveLoc(Loc loc, Scope *sc);
|
|
};
|
|
|
|
class PrettyFuncInitExp : public DefaultInitExp
|
|
{
|
|
public:
|
|
PrettyFuncInitExp(Loc loc);
|
|
Expression *semantic(Scope *sc);
|
|
Expression *resolveLoc(Loc loc, Scope *sc);
|
|
};
|
|
|
|
#endif
|
|
|
|
/****************************************************************/
|
|
|
|
#if IN_LLVM
|
|
|
|
// this stuff is strictly LDC
|
|
|
|
struct GEPExp : UnaExp
|
|
{
|
|
unsigned index;
|
|
Identifier* ident;
|
|
|
|
GEPExp(Loc loc, Expression* e, Identifier* id, unsigned idx);
|
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
|
Expression *toLvalue(Scope *sc, Expression *e);
|
|
|
|
DValue* toElem(IRState* irs);
|
|
};
|
|
|
|
#endif
|
|
|
|
/****************************************************************/
|
|
|
|
/* Special values used by the interpreter
|
|
*/
|
|
extern Expression *EXP_CANT_INTERPRET;
|
|
extern Expression *EXP_CONTINUE_INTERPRET;
|
|
extern Expression *EXP_BREAK_INTERPRET;
|
|
extern Expression *EXP_GOTO_INTERPRET;
|
|
extern Expression *EXP_VOID_INTERPRET;
|
|
|
|
Expression *expType(Type *type, Expression *e);
|
|
|
|
Expression *Neg(Type *type, Expression *e1);
|
|
Expression *Com(Type *type, Expression *e1);
|
|
Expression *Not(Type *type, Expression *e1);
|
|
Expression *Bool(Type *type, Expression *e1);
|
|
Expression *Cast(Type *type, Type *to, Expression *e1);
|
|
Expression *ArrayLength(Type *type, Expression *e1);
|
|
Expression *Ptr(Type *type, Expression *e1);
|
|
|
|
Expression *Add(Type *type, Expression *e1, Expression *e2);
|
|
Expression *Min(Type *type, Expression *e1, Expression *e2);
|
|
Expression *Mul(Type *type, Expression *e1, Expression *e2);
|
|
Expression *Div(Type *type, Expression *e1, Expression *e2);
|
|
Expression *Mod(Type *type, Expression *e1, Expression *e2);
|
|
Expression *Pow(Type *type, Expression *e1, Expression *e2);
|
|
Expression *Shl(Type *type, Expression *e1, Expression *e2);
|
|
Expression *Shr(Type *type, Expression *e1, Expression *e2);
|
|
Expression *Ushr(Type *type, Expression *e1, Expression *e2);
|
|
Expression *And(Type *type, Expression *e1, Expression *e2);
|
|
Expression *Or(Type *type, Expression *e1, Expression *e2);
|
|
Expression *Xor(Type *type, Expression *e1, Expression *e2);
|
|
Expression *Index(Type *type, Expression *e1, Expression *e2);
|
|
Expression *Cat(Type *type, Expression *e1, Expression *e2);
|
|
|
|
Expression *Equal(TOK op, Type *type, Expression *e1, Expression *e2);
|
|
Expression *Cmp(TOK op, Type *type, Expression *e1, Expression *e2);
|
|
Expression *Identity(TOK op, Type *type, Expression *e1, Expression *e2);
|
|
|
|
Expression *Slice(Type *type, Expression *e1, Expression *lwr, Expression *upr);
|
|
|
|
// Const-folding functions used by CTFE
|
|
|
|
void sliceAssignArrayLiteralFromString(ArrayLiteralExp *existingAE, StringExp *newval, size_t firstIndex);
|
|
void sliceAssignStringFromArrayLiteral(StringExp *existingSE, ArrayLiteralExp *newae, size_t firstIndex);
|
|
void sliceAssignStringFromString(StringExp *existingSE, StringExp *newstr, size_t firstIndex);
|
|
|
|
int sliceCmpStringWithString(StringExp *se1, StringExp *se2, size_t lo1, size_t lo2, size_t len);
|
|
int sliceCmpStringWithArray(StringExp *se1, ArrayLiteralExp *ae2, size_t lo1, size_t lo2, size_t len);
|
|
|
|
|
|
#endif /* DMD_EXPRESSION_H */
|