@@ -20,8 +20,10 @@ test-runner: build
ln -sf out/$(BUILDTYPE)/test test-runner

test: test-runner can
@./test-runner splaytree
@./test-runner parser
@./test-runner scope
@./test-runner fullgen
# @./test-runner hir
# @./test-runner lir
@./test-runner functional
@@ -29,6 +29,8 @@
'src/root.cc',
'src/visitor.cc',
'src/source-map.cc',
'src/fullgen.cc',
'src/fullgen-instructions.cc',
'src/hir.cc',
'src/hir-instructions.cc',
'src/lir.cc',
@@ -43,6 +45,7 @@
'src/x64/assembler-x64.cc',
'src/x64/macroassembler-x64.cc',
'src/x64/stubs-x64.cc',
'src/x64/fullgen-x64.cc',
'src/x64/lir-builder-x64.cc',
'src/x64/lir-x64.cc',
'src/x64/pic-x64.cc',
@@ -53,6 +56,7 @@
'src/ia32/assembler-ia32.cc',
'src/ia32/macroassembler-ia32.cc',
'src/ia32/stubs-ia32.cc',
'src/ia32/fullgen-ia32.cc',
'src/ia32/lir-builder-ia32.cc',
'src/ia32/lir-ia32.cc',
'src/ia32/pic-ia32.cc',
@@ -24,7 +24,7 @@
'GCC_VERSION': '4.1',
'GCC_WARN_ABOUT_MISSING_NEWLINE': 'YES', # -Wnewline-eof
'PREBINDING': 'NO', # No -Wl,-prebind
'MACOSX_DEPLOYMENT_TARGET': '10.5', # -mmacosx-version-min=10.5
'MACOSX_DEPLOYMENT_TARGET': '10.6', # -mmacosx-version-min=10.6
'USE_HEADERMAP': 'NO',
'WARNING_CFLAGS': [
'-Wall',
@@ -5,6 +5,8 @@
#include "parser.h" // Parser
#include "scope.h" // Scope
#include "macroassembler.h" // Masm
#include "fullgen.h" // Fullgen
#include "fullgen-inl.h" // Fullgen
#include "hir.h" // HIR
#include "hir-inl.h" // HIR
#include "lir.h" // LIR
@@ -143,24 +145,37 @@ char* CodeSpace::Compile(const char* filename,
// Add scope chunkrmation to variables (i.e. stack vs context, and indexes)
Scope::Analyze(ast);

// Generate CFG with SSA
HIRGen hir(heap(), chunk->filename(), ast);
Masm masm(this);

// Store root
*root = hir.root()->Allocate()->addr();
if (true) {
// Generate CFG with SSA
HIRGen hir(heap(), chunk->filename(), ast);

// Generate low-level representation
Masm masm(this);
// Store root
*root = hir.root()->Allocate()->addr();

// Generate low-level representation:
// For each root in reverse order generate lir
// (Generate children first, parents later)
HIRBlockList::Item* head = hir.roots()->head();
for (; head != NULL; head = head->next()) {
// Generate LIR
LGen lir(&hir, chunk->filename(), head->value());

// Generate Masm code
lir.Generate(&masm, heap()->source_map());
}
} else {
Fullgen f(heap(), chunk->filename());

// Create instruction list
f.Build(ast);

// For each root in reverse order generate lir
// (Generate children first, parents later)
HIRBlockList::Item* head = hir.roots()->head();
for (; head != NULL; head = head->next()) {
// Generate LIR
LGen lir(&hir, chunk->filename(), head->value());
// Store root
*root = f.root()->Allocate()->addr();

// Generate Masm code
lir.Generate(&masm, heap()->source_map());
// Generate instructions
f.Generate(&masm);
}

// Put code into code space
@@ -21,7 +21,7 @@ class Code;
class PIC;

typedef List<CodePage*, EmptyClass> CodePageList;
typedef List<CodeChunk*, EmptyClass> CodeChunkList;;
typedef List<CodeChunk*, EmptyClass> CodeChunkList;

class CodeSpace {
public:
@@ -0,0 +1,163 @@
#ifndef _SRC_FULLGEN_INL_H_
#define _SRC_FULLGEN_INL_H_

#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS
#endif // _STDC_FORMAT_MACROS

#include <inttypes.h> // PRIu64

#include "fullgen.h"
#include "fullgen-instructions.h"
#include "fullgen-instructions-inl.h"
#include "heap.h"

#include <assert.h>

namespace candor {
namespace internal {

inline FInstruction* Fullgen::Add(FInstruction* instr) {
instructions_.Push(instr);
instr->Init(this);
return instr;
}


inline FOperand* Fullgen::CreateOperand(ScopeSlot* slot) {
if (slot->is_stack()) {
return new FStackSlot(slot->index());
} else if (slot->is_context()) {
return new FContextSlot(slot->index(), slot->depth());
} else {
UNEXPECTED
}
}


inline void Fullgen::EmptySlots() {
while (free_slots_.length() > 0) free_slots_.Shift();
stack_index_ = 0;
}


inline FOperand* Fullgen::GetSlot() {
if (free_slots_.length() > 0) {
// Return previously created slot
return free_slots_.Pop();
}

// Create new slot
FOperand* slot = new FStackSlot(
current_function()->root_ast()->stack_slots() + stack_index_++);

return slot;
}


inline void Fullgen::ReleaseSlot(FOperand* slot) {
assert(slot != NULL);
free_slots_.Push(slot);
}


inline int Fullgen::instr_id() {
int res = instr_id_;
instr_id_ += 2;
return res;
}


inline FInstruction* Fullgen::GetNumber(uint64_t i) {
AstNode* index = new AstNode(AstNode::kNumber);

// Fast-case
if (i < 10) {
switch (i) {
case 0: index->value("0"); break;
case 1: index->value("1"); break;
case 2: index->value("2"); break;
case 3: index->value("3"); break;
case 4: index->value("4"); break;
case 5: index->value("5"); break;
case 6: index->value("6"); break;
case 7: index->value("7"); break;
case 8: index->value("8"); break;
case 9: index->value("9"); break;
default: UNEXPECTED
}
index->length(1);

return Visit(index);
}

char keystr[32];
index->value(keystr);
index->length(snprintf(keystr, sizeof(keystr), "%" PRIu64, i));

FInstruction* r = Visit(index);
r->ast(NULL);

return r;
}


inline FFunction* Fullgen::current_function() {
return current_function_;
}


inline void Fullgen::set_current_function(FFunction* current_function) {
current_function_ = current_function;
}


inline Root* Fullgen::root() {
return &root_;
}


inline SourceMap* Fullgen::source_map() {
return source_map_;
}


inline void Fullgen::Print(char* out, int32_t size) {
PrintBuffer p(out, size);
Print(&p);
}


inline bool FOperand::is_stack() {
return type_ == kStack;
}


inline bool FOperand::is_context() {
return type_ == kContext;
}


inline int FOperand::index() {
return index_;
}


inline int FOperand::depth() {
return depth_;
}


inline bool FOperand::operator==(FOperand* t) {
return type_ == t->type_ && index_ == t->index_ && depth_ == t->depth_;
}


inline FOperand* FScopedSlot::operand() {
return operand_;
}

} // namespace internal
} // namespace candor

#endif // _SRC_FULLGEN_INL_H_
@@ -0,0 +1,72 @@
#ifndef _SRC_FULLGEN_INSTRUCTION_INL_H_
#define _SRC_FULLGEN_INSTRUCTION_INL_H_

#include "fullgen.h"
#include "fullgen-inl.h"
#include "fullgen-instructions.h"
#include <assert.h> // assert

namespace candor {
namespace internal {

inline FInstruction* FInstruction::SetResult(FOperand* op) {
assert(result == NULL);
result = op;

return this;
}


inline FInstruction* FInstruction::AddArg(FOperand* op) {
assert(input_count_ < 3);
inputs[input_count_++] = op;

return this;
}


inline AstNode* FInstruction::ast() {
return ast_;
}


inline void FInstruction::ast(AstNode* ast) {
ast_ = ast;
}


inline FInstruction::Type FInstruction::type() {
return type_;
}

#define FULLGEN_INSTRUCTION_TYPE_TO_STR(V) \
case k##V: return #V;

inline const char* FInstruction::TypeToStr(Type type) {
switch (type) {
FULLGEN_INSTRUCTION_TYPES(FULLGEN_INSTRUCTION_TYPE_TO_STR)
default: UNEXPECTED break;
}
return "none";
}

#undef FULLGEN_INSTRUCTION_TYPE_TO_STR

inline AstNode* FFunction::root_ast() {
return root_ast_;
}


inline int FEntry::stack_slots() {
return stack_slots_;
}


inline void FEntry::stack_slots(int stack_slots) {
stack_slots_ = stack_slots;
}

} // namespace internal
} // namespace candor

#endif // _SRC_FULLGEN_INSTRUCTION_INL_H_