From: Chris Lattner Date: Sun, 22 Jun 2008 05:45:53 +0000 (+0000) Subject: add a new clang::APValue class at Eli's request. It is a discriminated X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8031a85dc88225723d960c7c142e4fe97c2f12fe;p=clang add a new clang::APValue class at Eli's request. It is a discriminated union between [potentially complex] APInt/APFloat. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@52609 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/clang.xcodeproj/project.pbxproj b/clang.xcodeproj/project.pbxproj index c757dd481f..ab33cfaacc 100644 --- a/clang.xcodeproj/project.pbxproj +++ b/clang.xcodeproj/project.pbxproj @@ -399,6 +399,7 @@ DE5932CE0AD60FF400BC794C /* clang.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = clang.h; path = Driver/clang.h; sourceTree = ""; }; DE5932CF0AD60FF400BC794C /* PrintParserCallbacks.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = PrintParserCallbacks.cpp; path = Driver/PrintParserCallbacks.cpp; sourceTree = ""; }; DE5932D00AD60FF400BC794C /* PrintPreprocessedOutput.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = PrintPreprocessedOutput.cpp; path = Driver/PrintPreprocessedOutput.cpp; sourceTree = ""; }; + DE613EF30E0E148D00B05B79 /* APValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = APValue.h; path = clang/AST/APValue.h; sourceTree = ""; }; DE67E70A0C020EC500F66BC5 /* SemaType.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SemaType.cpp; path = lib/Sema/SemaType.cpp; sourceTree = ""; }; DE67E70C0C020ECA00F66BC5 /* SemaStmt.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SemaStmt.cpp; path = lib/Sema/SemaStmt.cpp; sourceTree = ""; }; DE67E70E0C020ECF00F66BC5 /* SemaExprCXX.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SemaExprCXX.cpp; path = lib/Sema/SemaExprCXX.cpp; sourceTree = ""; }; @@ -768,22 +769,24 @@ DEC8D98B0A9433BC00353FCA /* AST */ = { isa = PBXGroup; children = ( - 35EE48AD0E0C4CB200715C54 /* DeclCXX.h */, - 35EE48AE0E0C4CB200715C54 /* ParentMap.h */, - 35CEA05A0DF9E82700A41296 /* ExprObjC.h */, + DE613EF30E0E148D00B05B79 /* APValue.h */, DEC8D9A30A94346E00353FCA /* AST.h */, 35BFBD2B0C9EDE1E006CB644 /* ASTConsumer.h */, DE75ED280B044DC90020CF81 /* ASTContext.h */, 1A72BEAC0D641E9400B085E9 /* Attr.h */, DED676D00B6C786700AAD4A3 /* Builtins.def */, DED676F90B6C797B00AAD4A3 /* Builtins.h */, + 1A68BC110D0CADDD001A28C8 /* PPCBuiltins.def */, + 1A68BC130D0CADDD001A28C8 /* X86Builtins.def */, DEC63B1B0C7B940600DBF169 /* CFG.h */, DEC8D9900A9433CD00353FCA /* Decl.h */, 035611470DA6A45C00D2EF2A /* DeclBase.h */, 84AF36A00CB17A3B00C820A5 /* DeclObjC.h */, + 35EE48AD0E0C4CB200715C54 /* DeclCXX.h */, DE0FCA620A95859D00248FD5 /* Expr.h */, 1A30A9E80B93A4C800201A91 /* ExprCXX.h */, - 1A68BC110D0CADDD001A28C8 /* PPCBuiltins.def */, + 35CEA05A0DF9E82700A41296 /* ExprObjC.h */, + 35EE48AE0E0C4CB200715C54 /* ParentMap.h */, 3547129D0C88881300B3E1D5 /* PrettyPrinter.h */, DE6951C60C4D1F5D00A5826B /* RecordLayout.h */, DE3452800AEF1B1800DBC861 /* Stmt.h */, @@ -794,7 +797,6 @@ 1A68BC120D0CADDD001A28C8 /* TargetBuiltins.h */, 35BB2D7A0D1994FA00944DB5 /* TranslationUnit.h */, DE3464210B03040900DBC861 /* Type.h */, - 1A68BC130D0CADDD001A28C8 /* X86Builtins.def */, ); name = AST; sourceTree = ""; diff --git a/include/clang/AST/APValue.h b/include/clang/AST/APValue.h new file mode 100644 index 0000000000..22d0cd1fb5 --- /dev/null +++ b/include/clang/AST/APValue.h @@ -0,0 +1,183 @@ +//===--- APValue.h - Union class for APFloat/APInt/Complex ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the APValue class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_APVALUE_H +#define LLVM_CLANG_AST_APVALUE_H + +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/APFloat.h" + +namespace clang { + +/// APValue - This class implements a discriminated union of [uninitialized] +/// [APInt] [APFloat], [Complex APInt] [Complex APFloat]. +class APValue { + typedef llvm::APInt APInt; + typedef llvm::APFloat APFloat; +public: + enum ValueKind { + Uninitialized, + Int, + Float, + ComplexInt, + ComplexFloat + }; +private: + ValueKind Kind; + + struct ComplexAPInt { APInt Real, Imag; }; + struct ComplexAPFloat { + APFloat Real, Imag; + ComplexAPFloat() : Real(0.0), Imag(0.0) {} + }; + + enum { + MaxSize = (sizeof(ComplexAPInt) > sizeof(ComplexAPFloat) ? + sizeof(ComplexAPInt) : sizeof(ComplexAPFloat)) + }; + + /// Data - space for the largest member in units of void*. This is an effort + /// to ensure that the APInt/APFloat values have proper alignment. + void *Data[(MaxSize+sizeof(void*)-1)/sizeof(void*)]; + +public: + APValue() : Kind(Uninitialized) {} + explicit APValue(const APInt &I) : Kind(Uninitialized) { + MakeInt(); setInt(I); + } + explicit APValue(const APFloat &F) : Kind(Uninitialized) { + MakeFloat(); setFloat(F); + } + APValue(const APInt &R, const APInt &I) : Kind(Uninitialized) { + MakeComplexInt(); setComplexInt(R, I); + } + APValue(const APFloat &R, const APFloat &I) : Kind(Uninitialized) { + MakeComplexFloat(); setComplexFloat(R, I); + } + APValue(const APValue &RHS) : Kind(Uninitialized) { + *this = RHS; + } + ~APValue() { + MakeUninit(); + } + + ValueKind getKind() const { return Kind; } + bool isUninit() const { return Kind == Uninitialized; } + bool isInt() const { return Kind == Int; } + bool isFloat() const { return Kind == Float; } + bool isComplexInt() const { return Kind == ComplexInt; } + bool isComplexFloat() const { return Kind == ComplexFloat; } + + const APInt &getInt() const { + assert(isInt() && "Invalid accessor"); + return *(const APInt*)(const void*)Data; + } + const APFloat &getFloat() const { + assert(isFloat() && "Invalid accessor"); + return *(const APFloat*)(const void*)Data; + } + const APInt &getComplexIntReal() const { + assert(isComplexInt() && "Invalid accessor"); + return ((const ComplexAPInt*)(const void*)Data)->Real; + } + const APInt &getComplexIntImag() const { + assert(isComplexInt() && "Invalid accessor"); + return ((const ComplexAPInt*)(const void*)Data)->Imag; + } + const APFloat &getComplexFloatReal() const { + assert(isComplexFloat() && "Invalid accessor"); + return ((const ComplexAPFloat*)(const void*)Data)->Real; + } + const APFloat &getComplexFloatImag() const { + assert(isComplexFloat() && "Invalid accessor"); + return ((const ComplexAPFloat*)(const void*)Data)->Imag; + } + + void setInt(const APInt &I) { + assert(isInt() && "Invalid accessor"); + *(APInt*)(void*)Data = I; + } + void setFloat(const APFloat &F) { + assert(isFloat() && "Invalid accessor"); + *(APFloat*)(void*)Data = F; + } + void setComplexInt(const APInt &R, const APInt &I) { + assert(isComplexInt() && "Invalid accessor"); + ((ComplexAPInt*)(void*)Data)->Real = R; + ((ComplexAPInt*)(void*)Data)->Imag = I; + } + void setComplexFloat(const APFloat &R, const APFloat &I) { + assert(isComplexFloat() && "Invalid accessor"); + ((ComplexAPFloat*)(void*)Data)->Real = R; + ((ComplexAPFloat*)(void*)Data)->Imag = I; + } + + const APValue &operator=(const APValue &RHS) { + if (Kind != RHS.Kind) { + MakeUninit(); + if (RHS.isInt()) + MakeInt(); + else if (RHS.isFloat()) + MakeFloat(); + else if (RHS.isComplexInt()) + MakeComplexInt(); + else if (RHS.isComplexFloat()) + MakeComplexFloat(); + } + if (isInt()) + setInt(RHS.getInt()); + else if (isFloat()) + setFloat(RHS.getFloat()); + else if (isComplexInt()) + setComplexInt(RHS.getComplexIntReal(), RHS.getComplexIntImag()); + else if (isComplexFloat()) + setComplexFloat(RHS.getComplexFloatReal(), RHS.getComplexFloatImag()); + return *this; + } + +private: + void MakeUninit() { + if (Kind == Int) + ((APInt*)(void*)Data)->~APInt(); + else if (Kind == Float) + ((APFloat*)(void*)Data)->~APFloat(); + else if (Kind == ComplexInt) + ((ComplexAPInt*)(void*)Data)->~ComplexAPInt(); + else if (Kind == ComplexFloat) + ((ComplexAPFloat*)(void*)Data)->~ComplexAPFloat(); + } + void MakeInt() { + assert(isUninit() && "Bad state change"); + new ((void*)Data) APInt(); + Kind = Int; + } + void MakeFloat() { + assert(isUninit() && "Bad state change"); + new ((APFloat*)(void*)Data) APFloat(0.0); + Kind = Float; + } + void MakeComplexInt() { + assert(isUninit() && "Bad state change"); + new ((ComplexAPInt*)(void*)Data) ComplexAPInt(); + Kind = ComplexInt; + } + void MakeComplexFloat() { + assert(isUninit() && "Bad state change"); + new ((ComplexAPFloat*)(void*)Data) ComplexAPFloat(); + Kind = ComplexFloat; + } +}; + +} + +#endif