Mercurial > projects > ldc
view gen/dvalue.h @ 1499:df11cdec45a2
Another shot at fixing the issues with (constant) struct literals and their addresses. See DMD2682, #218, #324.
The idea is to separate the notion of const from 'this variable can always be
replaced with its initializer' in the frontend. To do that, I introduced
Declaration::isSameAsInitializer, which is overridden in VarDeclaration to
return false for constants that have a struct literal initializer.
So
{{{
const S s = S(5);
void foo() { auto ps = &s; }
// is no longer replaced by
void foo() { auto ps = &(S(5)); }
}}}
To make taking the address of a struct constant with a struct-initializer
outside of function scope possible, I made sure that AddrExp::optimize doesn't
try to run the argument's optimization with WANTinterpret - that'd again
replace the constant with a struct literal temporary.
author | Christian Kamm <kamm incasoftware de> |
---|---|
date | Sun, 14 Jun 2009 19:49:58 +0200 |
parents | a5bfed1f6775 |
children |
line wrap: on
line source
#ifndef LDC_GEN_DVALUE_H #define LDC_GEN_DVALUE_H /* These classes are used for generating the IR. They encapsulate D values and provide a common interface to the most common operations. When more specialized handling is necessary, they hold enough information to do-the-right-thing (TM) */ #include <cassert> #include "root.h" struct Type; struct Dsymbol; struct VarDeclaration; struct FuncDeclaration; namespace llvm { class Value; class Type; class Constant; } struct DImValue; struct DConstValue; struct DNullValue; struct DVarValue; struct DFieldValue; struct DFuncValue; struct DSliceValue; // base class for d-values struct DValue : Object { Type* type; DValue(Type* ty) : type(ty) {} Type*& getType() { assert(type); return type; } virtual llvm::Value* getLVal() { assert(0); return 0; } virtual llvm::Value* getRVal() { assert(0); return 0; } virtual bool isLVal() { return false; } virtual DImValue* isIm() { return NULL; } virtual DConstValue* isConst() { return NULL; } virtual DNullValue* isNull() { return NULL; } virtual DVarValue* isVar() { return NULL; } virtual DFieldValue* isField() { return NULL; } virtual DSliceValue* isSlice() { return NULL; } virtual DFuncValue* isFunc() { return NULL; } protected: DValue() {} DValue(const DValue&) { } DValue& operator=(const DValue& other) { type = other.type; return *this; } }; // immediate d-value struct DImValue : DValue { llvm::Value* val; DImValue(Type* t, llvm::Value* v) : DValue(t), val(v) { } virtual llvm::Value* getRVal() { assert(val); return val; } virtual DImValue* isIm() { return this; } }; // constant d-value struct DConstValue : DValue { llvm::Constant* c; DConstValue(Type* t, llvm::Constant* con) : DValue(t), c(con) {} virtual llvm::Value* getRVal(); virtual DConstValue* isConst() { return this; } }; // null d-value struct DNullValue : DConstValue { DNullValue(Type* t, llvm::Constant* con) : DConstValue(t,con) {} virtual DNullValue* isNull() { return this; } }; // variable d-value struct DVarValue : DValue { VarDeclaration* var; llvm::Value* val; DVarValue(Type* t, VarDeclaration* vd, llvm::Value* llvmValue); DVarValue(Type* t, llvm::Value* llvmValue); virtual bool isLVal() { return true; } virtual llvm::Value* getLVal(); virtual llvm::Value* getRVal(); virtual DVarValue* isVar() { return this; } }; // field d-value struct DFieldValue : DVarValue { DFieldValue(Type* t, llvm::Value* llvmValue) : DVarValue(t, llvmValue) {} virtual DFieldValue* isField() { return this; } }; // slice d-value struct DSliceValue : DValue { llvm::Value* len; llvm::Value* ptr; DSliceValue(Type* t, llvm::Value* l, llvm::Value* p) : DValue(t), len(l), ptr(p) {} virtual llvm::Value* getRVal(); virtual DSliceValue* isSlice() { return this; } }; // function d-value struct DFuncValue : DValue { FuncDeclaration* func; llvm::Value* val; llvm::Value* vthis; DFuncValue(FuncDeclaration* fd, llvm::Value* v, llvm::Value* vt = 0); virtual llvm::Value* getRVal(); virtual DFuncValue* isFunc() { return this; } }; #endif // LDC_GEN_DVALUE_H