mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-13 20:32:21 +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++ -*--=//
|
||||
//
|
||||
// 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
|
||||
// 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
|
||||
#define LLVM_GLOBAL_VARIABLE_H
|
||||
|
||||
#include "llvm/Value.h"
|
||||
#include "llvm/User.h"
|
||||
class Module;
|
||||
class ConstPoolVal;
|
||||
class PointerType;
|
||||
|
||||
class GlobalVariable : public Value {
|
||||
class GlobalVariable : public User {
|
||||
Module *Parent; // The module that contains this method
|
||||
|
||||
friend class ValueHolder<GlobalVariable, Module, Module>;
|
||||
void setParent(Module *parent) { Parent = parent; }
|
||||
|
||||
bool Constant; // Is this a global constant?
|
||||
public:
|
||||
GlobalVariable(const Type *Ty, const string &Name = "");
|
||||
GlobalVariable(const Type *Ty, bool isConstant, ConstPoolVal *Initializer = 0,
|
||||
const string &Name = "");
|
||||
~GlobalVariable() {}
|
||||
|
||||
// getType - Global variables are always pointers
|
||||
inline const PointerType *getType() const {
|
||||
return (const PointerType*)User::getType();
|
||||
}
|
||||
|
||||
// Specialize setName to handle symbol table majik...
|
||||
virtual void setName(const string &name, SymbolTable *ST = 0);
|
||||
|
||||
inline Module *getParent() { 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
|
||||
|
@ -323,14 +323,29 @@ bool BytecodeParser::ParseModuleGlobalInfo(const uchar *&Buf, const uchar *End,
|
||||
unsigned VarType;
|
||||
if (read_vbr(Buf, End, VarType)) return failure(true);
|
||||
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()) {
|
||||
cerr << "Global not pointer type! Ty = " << Ty << endl;
|
||||
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...
|
||||
GlobalVariable *GV = new GlobalVariable(Ty);
|
||||
GlobalVariable *GV = new GlobalVariable(Ty, VarType & 1, Initializer);
|
||||
insertValue(GV, ModuleValues);
|
||||
C->getGlobalList().push_back(GV);
|
||||
|
||||
|
@ -223,11 +223,13 @@ int SlotCalculator::getValSlot(const Value *D) const {
|
||||
|
||||
|
||||
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
|
||||
// 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));
|
||||
}
|
||||
|
||||
|
@ -120,9 +120,21 @@ void BytecodeWriter::outputModuleInfoBlock(const Module *M) {
|
||||
|
||||
// Output the types for the global variables in the module...
|
||||
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!");
|
||||
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);
|
||||
|
||||
|
@ -123,9 +123,17 @@ void AssemblyWriter::processModule(const Module *M) {
|
||||
}
|
||||
|
||||
void AssemblyWriter::processGlobal(const GlobalVariable *GV) {
|
||||
Out << "global ";
|
||||
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::GlobalVariable(const Type *Ty, const string &Name = "")
|
||||
: Value(Ty, Value::GlobalVal, Name), Parent(0) {
|
||||
GlobalVariable::GlobalVariable(const Type *Ty, bool isConstant,
|
||||
ConstPoolVal *Initializer = 0,
|
||||
const string &Name = "")
|
||||
: User(Ty, Value::GlobalVal, Name), Parent(0), Constant(isConstant) {
|
||||
assert(Ty->isPointerType() && // No unsized array pointers
|
||||
(!Ty->dyncastPointerType()->isArrayType() ||
|
||||
Ty->dyncastPointerType()->dyncastArrayType()->isSized()) &&
|
||||
(!Ty->castPointerType()->isArrayType() ||
|
||||
Ty->castPointerType()->castArrayType()->isSized()) &&
|
||||
"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
|
||||
|
@ -223,11 +223,13 @@ int SlotCalculator::getValSlot(const Value *D) const {
|
||||
|
||||
|
||||
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
|
||||
// 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));
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user