mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-07-21 02:29:22 +00:00
Add support for global constants, and for initializers for constants
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@598 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
1781acab34
commit
d70684f758
@ -1,34 +1,64 @@
|
|||||||
//===-- llvm/Global.h - Class to represent a global variable -----*- C++ -*--=//
|
//===-- llvm/Global.h - Class to represent a global variable -----*- C++ -*--=//
|
||||||
//
|
//
|
||||||
// This file contains the declaration of the GlobalVariable class, which
|
// This file contains the declaration of the GlobalVariable class, which
|
||||||
// represents a single global variable in the VM.
|
// represents a single global variable (or constant) in the VM.
|
||||||
//
|
//
|
||||||
// Global variables are constant pointers that refer to hunks of space that are
|
// Global variables are constant pointers that refer to hunks of space that are
|
||||||
// allocated by either the VM, or by the linker in a static compiler.
|
// allocated by either the VM, or by the linker in a static compiler. A global
|
||||||
|
// variable may have an intial value, which is copied into the executables .data
|
||||||
|
// area. Global Constants are required to have initializers.
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#ifndef LLVM_GLOBAL_VARIABLE_H
|
#ifndef LLVM_GLOBAL_VARIABLE_H
|
||||||
#define LLVM_GLOBAL_VARIABLE_H
|
#define LLVM_GLOBAL_VARIABLE_H
|
||||||
|
|
||||||
#include "llvm/Value.h"
|
#include "llvm/User.h"
|
||||||
class Module;
|
class Module;
|
||||||
|
class ConstPoolVal;
|
||||||
|
class PointerType;
|
||||||
|
|
||||||
class GlobalVariable : public Value {
|
class GlobalVariable : public User {
|
||||||
Module *Parent; // The module that contains this method
|
Module *Parent; // The module that contains this method
|
||||||
|
|
||||||
friend class ValueHolder<GlobalVariable, Module, Module>;
|
friend class ValueHolder<GlobalVariable, Module, Module>;
|
||||||
void setParent(Module *parent) { Parent = parent; }
|
void setParent(Module *parent) { Parent = parent; }
|
||||||
|
|
||||||
|
bool Constant; // Is this a global constant?
|
||||||
public:
|
public:
|
||||||
GlobalVariable(const Type *Ty, const string &Name = "");
|
GlobalVariable(const Type *Ty, bool isConstant, ConstPoolVal *Initializer = 0,
|
||||||
|
const string &Name = "");
|
||||||
~GlobalVariable() {}
|
~GlobalVariable() {}
|
||||||
|
|
||||||
|
// getType - Global variables are always pointers
|
||||||
|
inline const PointerType *getType() const {
|
||||||
|
return (const PointerType*)User::getType();
|
||||||
|
}
|
||||||
|
|
||||||
// Specialize setName to handle symbol table majik...
|
// Specialize setName to handle symbol table majik...
|
||||||
virtual void setName(const string &name, SymbolTable *ST = 0);
|
virtual void setName(const string &name, SymbolTable *ST = 0);
|
||||||
|
|
||||||
inline Module *getParent() { return Parent; }
|
inline Module *getParent() { return Parent; }
|
||||||
inline const Module *getParent() const { return Parent; }
|
inline const Module *getParent() const { return Parent; }
|
||||||
|
|
||||||
|
// The initializer for the global variable/constant is held by Operands[0] if
|
||||||
|
// an initializer is specified.
|
||||||
|
//
|
||||||
|
inline bool hasInitializer() const { return !Operands.empty(); }
|
||||||
|
inline const ConstPoolVal *getInitializer() const {
|
||||||
|
return Operands[0]->castConstantAsserting();
|
||||||
|
}
|
||||||
|
inline ConstPoolVal *getInitializer() {
|
||||||
|
return Operands[0]->castConstantAsserting();
|
||||||
|
}
|
||||||
|
inline void setInitializer(ConstPoolVal *CPV) { Operands[0] = (Value*)CPV; }
|
||||||
|
|
||||||
|
|
||||||
|
// If the value is a global constant, its value is immutable throughout the
|
||||||
|
// runtime execution of the program. Assigning a value into the constant
|
||||||
|
// leads to undefined behavior.
|
||||||
|
//
|
||||||
|
inline bool isConstant() const { return Constant; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -323,14 +323,29 @@ bool BytecodeParser::ParseModuleGlobalInfo(const uchar *&Buf, const uchar *End,
|
|||||||
unsigned VarType;
|
unsigned VarType;
|
||||||
if (read_vbr(Buf, End, VarType)) return failure(true);
|
if (read_vbr(Buf, End, VarType)) return failure(true);
|
||||||
while (VarType != Type::VoidTyID) { // List is terminated by Void
|
while (VarType != Type::VoidTyID) { // List is terminated by Void
|
||||||
const Type *Ty = getType(VarType);
|
// VarType Fields: bit0 = isConstant, bit1 = hasInitializer, bit2+ = slot#
|
||||||
|
const Type *Ty = getType(VarType >> 2);
|
||||||
if (!Ty || !Ty->isPointerType()) {
|
if (!Ty || !Ty->isPointerType()) {
|
||||||
cerr << "Global not pointer type! Ty = " << Ty << endl;
|
cerr << "Global not pointer type! Ty = " << Ty << endl;
|
||||||
return failure(true);
|
return failure(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ConstPoolVal *Initializer = 0;
|
||||||
|
if (VarType & 2) { // Does it have an initalizer?
|
||||||
|
// Do not improvise... values must have been stored in the constant pool,
|
||||||
|
// which should have been read before now.
|
||||||
|
//
|
||||||
|
unsigned InitSlot;
|
||||||
|
if (read_vbr(Buf, End, InitSlot)) return failure(true);
|
||||||
|
|
||||||
|
Value *V = getValue(Ty->castPointerType()->getValueType(),
|
||||||
|
InitSlot, false);
|
||||||
|
if (V == 0) return failure(true);
|
||||||
|
Initializer = V->castConstantAsserting();
|
||||||
|
}
|
||||||
|
|
||||||
// Create the global variable...
|
// Create the global variable...
|
||||||
GlobalVariable *GV = new GlobalVariable(Ty);
|
GlobalVariable *GV = new GlobalVariable(Ty, VarType & 1, Initializer);
|
||||||
insertValue(GV, ModuleValues);
|
insertValue(GV, ModuleValues);
|
||||||
C->getGlobalList().push_back(GV);
|
C->getGlobalList().push_back(GV);
|
||||||
|
|
||||||
|
@ -223,11 +223,13 @@ int SlotCalculator::getValSlot(const Value *D) const {
|
|||||||
|
|
||||||
|
|
||||||
int SlotCalculator::insertValue(const Value *D) {
|
int SlotCalculator::insertValue(const Value *D) {
|
||||||
if (const ConstPoolVal *CPV = D->castConstant()) {
|
if (D->isConstant() || D->isGlobal()) {
|
||||||
|
const User *U = (const User *)D;
|
||||||
// This makes sure that if a constant has uses (for example an array
|
// This makes sure that if a constant has uses (for example an array
|
||||||
// of const ints), that they are inserted also.
|
// of const ints), that they are inserted also. Same for global variable
|
||||||
|
// initializers.
|
||||||
//
|
//
|
||||||
for_each(CPV->op_begin(), CPV->op_end(),
|
for_each(U->op_begin(), U->op_end(),
|
||||||
bind_obj(this, &SlotCalculator::insertValue));
|
bind_obj(this, &SlotCalculator::insertValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,9 +120,21 @@ void BytecodeWriter::outputModuleInfoBlock(const Module *M) {
|
|||||||
|
|
||||||
// Output the types for the global variables in the module...
|
// Output the types for the global variables in the module...
|
||||||
for (Module::const_giterator I = M->gbegin(), End = M->gend(); I != End;++I) {
|
for (Module::const_giterator I = M->gbegin(), End = M->gend(); I != End;++I) {
|
||||||
int Slot = Table.getValSlot((*I)->getType());
|
const GlobalVariable *GV = *I;
|
||||||
|
int Slot = Table.getValSlot(GV->getType());
|
||||||
assert(Slot != -1 && "Module global vars is broken!");
|
assert(Slot != -1 && "Module global vars is broken!");
|
||||||
output_vbr((unsigned)Slot, Out);
|
|
||||||
|
// Fields: bit0 = isConstant, bit1 = hasInitializer, bit2+ = slot#
|
||||||
|
unsigned oSlot = ((unsigned)Slot << 2) | (GV->hasInitializer() << 1) |
|
||||||
|
GV->isConstant();
|
||||||
|
output_vbr(oSlot, Out);
|
||||||
|
|
||||||
|
// If we have an initialized, output it now.
|
||||||
|
if (GV->hasInitializer()) {
|
||||||
|
Slot = Table.getValSlot(GV->getInitializer());
|
||||||
|
assert(Slot != -1 && "No slot for global var initializer!");
|
||||||
|
output_vbr((unsigned)Slot, Out);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
output_vbr((unsigned)Table.getValSlot(Type::VoidTy), Out);
|
output_vbr((unsigned)Table.getValSlot(Type::VoidTy), Out);
|
||||||
|
|
||||||
|
@ -123,9 +123,17 @@ void AssemblyWriter::processModule(const Module *M) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AssemblyWriter::processGlobal(const GlobalVariable *GV) {
|
void AssemblyWriter::processGlobal(const GlobalVariable *GV) {
|
||||||
Out << "global ";
|
|
||||||
if (GV->hasName()) Out << "%" << GV->getName() << " = ";
|
if (GV->hasName()) Out << "%" << GV->getName() << " = ";
|
||||||
Out << GV->getType()->getDescription() << endl;
|
|
||||||
|
if (!GV->hasInitializer()) Out << "uninitialized ";
|
||||||
|
|
||||||
|
Out << (GV->isConstant() ? "constant " : "global ")
|
||||||
|
<< GV->getType()->getValueType()->getDescription();
|
||||||
|
|
||||||
|
if (GV->hasInitializer())
|
||||||
|
writeOperand(GV->getInitializer(), false, false);
|
||||||
|
|
||||||
|
Out << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -82,12 +82,18 @@ void Method::dropAllReferences() {
|
|||||||
// GlobalVariable Implementation
|
// GlobalVariable Implementation
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
GlobalVariable::GlobalVariable(const Type *Ty, const string &Name = "")
|
GlobalVariable::GlobalVariable(const Type *Ty, bool isConstant,
|
||||||
: Value(Ty, Value::GlobalVal, Name), Parent(0) {
|
ConstPoolVal *Initializer = 0,
|
||||||
|
const string &Name = "")
|
||||||
|
: User(Ty, Value::GlobalVal, Name), Parent(0), Constant(isConstant) {
|
||||||
assert(Ty->isPointerType() && // No unsized array pointers
|
assert(Ty->isPointerType() && // No unsized array pointers
|
||||||
(!Ty->dyncastPointerType()->isArrayType() ||
|
(!Ty->castPointerType()->isArrayType() ||
|
||||||
Ty->dyncastPointerType()->dyncastArrayType()->isSized()) &&
|
Ty->castPointerType()->castArrayType()->isSized()) &&
|
||||||
"Global Variables must be pointers to a sized type!");
|
"Global Variables must be pointers to a sized type!");
|
||||||
|
if (Initializer) Operands.push_back(Use((Value*)Initializer, this));
|
||||||
|
|
||||||
|
assert(!isConstant || hasInitializer() &&
|
||||||
|
"Globals Constants must have an initializer!");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Specialize setName to take care of symbol table majik
|
// Specialize setName to take care of symbol table majik
|
||||||
|
@ -223,11 +223,13 @@ int SlotCalculator::getValSlot(const Value *D) const {
|
|||||||
|
|
||||||
|
|
||||||
int SlotCalculator::insertValue(const Value *D) {
|
int SlotCalculator::insertValue(const Value *D) {
|
||||||
if (const ConstPoolVal *CPV = D->castConstant()) {
|
if (D->isConstant() || D->isGlobal()) {
|
||||||
|
const User *U = (const User *)D;
|
||||||
// This makes sure that if a constant has uses (for example an array
|
// This makes sure that if a constant has uses (for example an array
|
||||||
// of const ints), that they are inserted also.
|
// of const ints), that they are inserted also. Same for global variable
|
||||||
|
// initializers.
|
||||||
//
|
//
|
||||||
for_each(CPV->op_begin(), CPV->op_end(),
|
for_each(U->op_begin(), U->op_end(),
|
||||||
bind_obj(this, &SlotCalculator::insertValue));
|
bind_obj(this, &SlotCalculator::insertValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user