summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt2
-rw-r--r--Lexer.l3
-rw-r--r--Parser.y18
-rw-r--r--Version.cc3
-rw-r--r--main.cc48
-rw-r--r--node/StatementNode.cc86
-rw-r--r--node/StatementNode.hh16
-rw-r--r--t/extern.pas13
-rw-r--r--t/trivial.ll591
9 files changed, 763 insertions, 17 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a65252a..f403ace 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -54,5 +54,5 @@ add_definitions(-DPCC_OSNAME="${CMAKE_SYSTEM}")
add_executable(pcc ${PCC_SOURCE})
target_include_directories(pcc PRIVATE ${PCC_INCLUDE})
-llvm_map_components_to_libnames(llvm_libs support core)
+llvm_map_components_to_libnames(llvm_libs support core x86asmparser x86codegen)
target_link_libraries(pcc ${llvm_libs})
diff --git a/Lexer.l b/Lexer.l
index 861806d..e69ddb0 100644
--- a/Lexer.l
+++ b/Lexer.l
@@ -111,6 +111,9 @@ white [\t\f\r ]
"do" {return Parser::make_DO(loc);}
"repeat" {return Parser::make_REPEAT(loc);}
"until" {return Parser::make_UNTIL(loc);}
+"for" {return Parser::make_FOR(loc);}
+"to" {return Parser::make_TO(true, loc);}
+"downto" {return Parser::make_TO(false, loc);}
"break" {return Parser::make_BREAK(loc);}
"continue" {return Parser::make_CONTINUE(loc);}
diff --git a/Parser.y b/Parser.y
index 34d8b03..f4e9779 100644
--- a/Parser.y
+++ b/Parser.y
@@ -44,7 +44,7 @@ YY_DECL;
%token FILE_END 0;
%token COLON SEMICOLON COMMA DOTDOT DOT ASSIGN LBRACKET RBRACKET LPARENTHESIS RPARENTHESIS
%token PROGRAM IDENTIFIER VAR CONST TYPE BEGINS ENDS FUNCTION EXTERN DOTDOTDOT
-%token IF THEN ELSE WHILE DO REPEAT UNTIL BREAK CONTINUE
+%token IF THEN ELSE WHILE DO REPEAT UNTIL BREAK CONTINUE FOR TO
%token VOID BOOLEAN CHAR INTEGER REAL STRING ARRAY OF RECORD
%token ADD SUB MUL REAL_DIV DIV MOD LT LE GT GE EQ NE CARET AT
%token AND NOT OR XOR SHL SHR
@@ -61,7 +61,7 @@ YY_DECL;
%type <pcc::Declaration> type_decl member_decl
%type <std::shared_ptr<TypeIdentifier>> type array_type record_type
-%type <bool> BOOLEAN_LITERAL
+%type <bool> BOOLEAN_LITERAL TO
%type <char> CHAR_LITERAL
%type <int> INTEGER_LITERAL
%type <float> REAL_LITERAL
@@ -213,15 +213,17 @@ statement
;
open_statement
- : IF expression THEN statement {$$=std::make_shared<pcc::IfStatementNode>(ctx, $2, $4, nullptr);}
- | IF expression THEN closed_statement ELSE open_statement {$$=std::make_shared<pcc::IfStatementNode>(ctx, $2, $4, $6);}
- | WHILE expression DO open_statement {$$=std::make_shared<pcc::WhileStatementNode>(ctx, $2, $4);}
+ : IF expression THEN statement {$$=std::make_shared<pcc::IfStatementNode>(ctx, $2, $4, nullptr);}
+ | IF expression THEN closed_statement ELSE open_statement {$$=std::make_shared<pcc::IfStatementNode>(ctx, $2, $4, $6);}
+ | WHILE expression DO open_statement {$$=std::make_shared<pcc::WhileStatementNode>(ctx, $2, $4);}
+ | FOR lvalue ASSIGN expression TO expression DO open_statement {$$=std::make_shared<pcc::ForStatementNode>(ctx, $2, $4, $6, $5, $8);}
;
closed_statement
- : normal_statement {$$=$1;}
- | IF expression THEN closed_statement ELSE closed_statement {$$=std::make_shared<pcc::IfStatementNode>(ctx, $2, $4, $6);}
- | WHILE expression DO closed_statement {$$=std::make_shared<pcc::WhileStatementNode>(ctx, $2, $4);}
+ : normal_statement {$$=$1;}
+ | IF expression THEN closed_statement ELSE closed_statement {$$=std::make_shared<pcc::IfStatementNode>(ctx, $2, $4, $6);}
+ | WHILE expression DO closed_statement {$$=std::make_shared<pcc::WhileStatementNode>(ctx, $2, $4);}
+ | FOR lvalue ASSIGN expression TO expression DO closed_statement {$$=std::make_shared<pcc::ForStatementNode>(ctx, $2, $4, $6, $5, $8);}
;
normal_statement
diff --git a/Version.cc b/Version.cc
index c3c432f..02e30e2 100644
--- a/Version.cc
+++ b/Version.cc
@@ -29,7 +29,8 @@ PCC_NORETURN void ShowHelp() {
<< " -v Verbose mode.\n"
" -vv Very verbose mode.\n"
" -V Show version and exit.\n"
- " -h Show this help and exit."
+ " -h Show this help and exit.\n"
+ " -t Set target's triple."
<< std::endl;
std::exit(0);
}
diff --git a/main.cc b/main.cc
index 21baac1..7597984 100644
--- a/main.cc
+++ b/main.cc
@@ -6,7 +6,10 @@
#include <unistd.h>
#endif
+#include <llvm/Support/TargetRegistry.h>
+#include <llvm/Support/TargetSelect.h>
#include <llvm/Support/raw_ostream.h>
+#include <llvm/Target/TargetMachine.h>
#include "Driver.hh"
#include "Log.hh"
@@ -15,7 +18,8 @@
int main(int argc, char* argv[]) {
int rv;
int level = pcc::ToUnderlying(pcc::PCC_WARNING);
- while ((rv = getopt(argc, argv, "vVh")) != -1) {
+ std::string triple = "";
+ while ((rv = getopt(argc, argv, "vVht:")) != -1) {
switch (rv) {
case 'v':
level = (level == 0 ? 0 : level - 1);
@@ -24,25 +28,61 @@ int main(int argc, char* argv[]) {
pcc::ShowVersion();
case 'h':
pcc::ShowHelp();
+ case 't':
+ triple = optarg;
default:
pcc::Log(pcc::PCC_ERROR, "Unknown option \"%c\".", rv);
pcc::ShowHelp();
}
}
pcc::SetLogLevel(static_cast<pcc::LogLevel>(level));
+ llvm::InitializeAllTargetInfos();
+ llvm::InitializeAllTargets();
+ llvm::InitializeAllTargetMCs();
+ llvm::InitializeAllAsmParsers();
+ llvm::InitializeAllAsmPrinters();
+ if (triple.empty()) {
+ triple = llvm::sys::getDefaultTargetTriple();
+ }
+ std::string error;
+ const llvm::Target* target =
+ llvm::TargetRegistry::lookupTarget(triple, error);
+ if (!error.empty()) {
+ pcc::Log(pcc::PCC_ERROR,
+ "failed to find target with triple %s, reason %s",
+ triple.c_str(), error.c_str());
+ return -1;
+ }
+ std::string cpu = "generic";
+ std::string features = "";
+ llvm::TargetOptions options;
+ llvm::TargetMachine* machine =
+ target->createTargetMachine(triple, cpu, features, options, llvm::None);
+ llvm::DataLayout layout = machine->createDataLayout();
if (optind >= argc) {
pcc::Log(pcc::PCC_ERROR, "No input file specified");
- return 0;
+ return -1;
}
for (int i = optind; i < argc; i++) {
pcc::Driver driver(argv[i]);
+ llvm::Module* module = driver.GetContext()->GetModule();
+ module->setTargetTriple(triple);
+ module->setDataLayout(layout);
std::string filename(argv[i]);
std::shared_ptr<pcc::ProgramNode> root = driver.Parse(filename);
if (root != nullptr) {
root->CodeGen();
}
- driver.GetContext()->GetModule()->print(llvm::errs(), nullptr);
+ size_t PostfixPos = filename.rfind(".pas");
+ std::string OutputFileName;
+ if (PostfixPos == std::string::npos) {
+ OutputFileName = filename + ".ll";
+ } else {
+ OutputFileName = filename.substr(0, PostfixPos) + ".ll";
+ }
+ std::error_code ErrorCode;
+ llvm::raw_fd_ostream Output(OutputFileName, ErrorCode);
+ driver.GetContext()->GetModule()->print(Output, nullptr);
}
-
return 0;
}
diff --git a/node/StatementNode.cc b/node/StatementNode.cc
index b6e1189..07babe2 100644
--- a/node/StatementNode.cc
+++ b/node/StatementNode.cc
@@ -39,6 +39,7 @@ Value AssignStatementNode::CodeGen() {
"type %s is not a valid pointer type, can't store anything into "
"this lvalue",
lhs_->GetType()->GetCommonName());
+ return nullptr;
}
RightValue = context_->GetTypeManager()->CreateCast(
LeftType->GetElementType(), rhs_->GetType(), RightValue, context_);
@@ -132,6 +133,7 @@ Value WhileStatementNode::CodeGen() {
builder->SetInsertPoint(LoopBlock);
context_->PushBreakDestination(EndBlock);
context_->PushContinueDestination(StartBlock);
+ context_->SetJumpingFlag(false);
WhileBody_->CodeGen();
context_->PopBreakDestination();
context_->PopContinueDestination();
@@ -164,6 +166,7 @@ Value RepeatStatementNode::CodeGen() {
builder->SetInsertPoint(LoopBlock);
context_->PushBreakDestination(EndBlock);
context_->PushContinueDestination(CheckBlock);
+ context_->SetJumpingFlag(false);
RepeatBody_->CodeGen();
context_->PopBreakDestination();
context_->PopContinueDestination();
@@ -178,6 +181,89 @@ Value RepeatStatementNode::CodeGen() {
return nullptr;
}
+ForStatementNode::ForStatementNode(Context* context,
+ std::shared_ptr<ExprNode> variable,
+ std::shared_ptr<ExprNode> start,
+ std::shared_ptr<ExprNode> end, bool IsUpward,
+ std::shared_ptr<BaseNode> ForBody)
+ : BaseNode(context)
+ , variable_(variable)
+ , start_(start)
+ , end_(end)
+ , IsUpward_(IsUpward)
+ , ForBody_(ForBody) {}
+
+Value ForStatementNode::CodeGen() {
+ llvm::IRBuilder<>* builder = context_->GetBuilder();
+ TypeManager* manager = context_->GetTypeManager();
+ std::shared_ptr<Type> boolean =
+ manager->GetBuiltinType(BuiltinType::BOOLEAN);
+ llvm::Function* body = builder->GetInsertBlock()->getParent();
+ llvm::BasicBlock* StartBlock =
+ llvm::BasicBlock::Create(GlobalLLVMContext, "start", body);
+ llvm::BasicBlock* LoopBlock =
+ llvm::BasicBlock::Create(GlobalLLVMContext, "loop");
+ llvm::BasicBlock* IncrementBlock =
+ llvm::BasicBlock::Create(GlobalLLVMContext, "increment");
+ llvm::BasicBlock* EndBlock =
+ llvm::BasicBlock::Create(GlobalLLVMContext, "done");
+ Value LoopValue = variable_->CodeGen();
+ std::shared_ptr<PointerType> LoopPointer =
+ std::dynamic_pointer_cast<PointerType>(variable_->GetType());
+ if (LoopPointer == nullptr) {
+ Log(LogLevel::PCC_ERROR,
+ "type %s is not a valid pointer type, can't store anything into "
+ "this lvalue",
+ variable_->GetType()->GetCommonName());
+ return nullptr;
+ }
+ std::shared_ptr<IntegerBaseType> LoopType =
+ std::dynamic_pointer_cast<IntegerBaseType>(
+ LoopPointer->GetElementType());
+ if (LoopType == nullptr) {
+ Log(LogLevel::PCC_ERROR,
+ "loop variable should have a integer-like type, not %s",
+ LoopPointer->GetElementType()->GetCommonName());
+ return nullptr;
+ }
+ Value StartValue = start_->CodeGen();
+ StartValue =
+ manager->CreateCast(LoopType, start_->GetType(), StartValue, context_);
+ builder->CreateStore(StartValue, LoopValue);
+ builder->CreateBr(StartBlock);
+ builder->SetInsertPoint(StartBlock);
+ Value EndValue = end_->CodeGen();
+ EndValue =
+ manager->CreateCast(LoopType, end_->GetType(), EndValue, context_);
+ Value LoadedLoopValue =
+ builder->CreateLoad(LoopType->GetLLVMType(), LoopValue);
+ Value cond = builder->CreateICmp(IsUpward_ ? llvm::CmpInst::ICMP_SLE
+ : llvm::CmpInst::ICMP_SGE,
+ LoadedLoopValue, EndValue);
+ builder->CreateCondBr(cond, LoopBlock, EndBlock);
+ body->getBasicBlockList().push_back(LoopBlock);
+ builder->SetInsertPoint(LoopBlock);
+ context_->PushBreakDestination(EndBlock);
+ context_->PushContinueDestination(IncrementBlock);
+ context_->SetJumpingFlag(false);
+ ForBody_->CodeGen();
+ context_->PopBreakDestination();
+ context_->PopContinueDestination();
+ builder->CreateBr(IncrementBlock);
+ body->getBasicBlockList().push_back(IncrementBlock);
+ builder->SetInsertPoint(IncrementBlock);
+ LoadedLoopValue = builder->CreateLoad(LoopType->GetLLVMType(), LoopValue);
+ Value one = llvm::ConstantInt::get(LoopType->GetLLVMType(), 1);
+ Value NewLoopValue = builder->CreateBinOp(
+ IsUpward_ ? llvm::BinaryOperator::Add : llvm::BinaryOperator::Sub,
+ LoadedLoopValue, one);
+ builder->CreateStore(NewLoopValue, LoopValue);
+ builder->CreateBr(StartBlock);
+ body->getBasicBlockList().push_back(EndBlock);
+ builder->SetInsertPoint(EndBlock);
+ return nullptr;
+}
+
BreakStatementNode::BreakStatementNode(Context* context)
: BaseNode(context) {}
diff --git a/node/StatementNode.hh b/node/StatementNode.hh
index 66c2517..fa8fbe4 100644
--- a/node/StatementNode.hh
+++ b/node/StatementNode.hh
@@ -69,6 +69,22 @@ class RepeatStatementNode : public BaseNode {
std::shared_ptr<BaseNode> RepeatBody_;
};
+class ForStatementNode : public BaseNode {
+ public:
+ ForStatementNode(Context* context, std::shared_ptr<ExprNode> variable,
+ std::shared_ptr<ExprNode> start,
+ std::shared_ptr<ExprNode> end, bool IsUpward,
+ std::shared_ptr<BaseNode> ForBody);
+ virtual Value CodeGen() override;
+
+ protected:
+ std::shared_ptr<ExprNode> variable_;
+ std::shared_ptr<ExprNode> start_;
+ std::shared_ptr<ExprNode> end_;
+ bool IsUpward_;
+ std::shared_ptr<BaseNode> ForBody_;
+};
+
class BreakStatementNode : public BaseNode {
public:
BreakStatementNode(Context* context);
diff --git a/t/extern.pas b/t/extern.pas
index 0b78e45..a23c371 100644
--- a/t/extern.pas
+++ b/t/extern.pas
@@ -7,9 +7,16 @@ extern __isoc99_scanf(s:string, ...):integer;
function main():integer;
var
buf:array[0..1023] of char;
+ i:integer;
begin
puts('Hello, World!');
- printf('Variadic Function Test: %d, %s, %x\nsay something:', 1, 'yes', 0x12345678);
- __isoc99_scanf('%s', @buf);
- printf('you said: %s\n', @buf)
+ printf('Variadic Function Test: %d, %s, %x\n', 1, 'yes', 0x12345678);
+ for i:=0 to 10 do
+ begin
+ if i=3 then continue;
+ if i=5 then break;
+ printf('say something: ');
+ __isoc99_scanf('%s', @buf[0]);
+ printf('round %d you said: %s\n', i, @buf[0])
+ end;
end;
diff --git a/t/trivial.ll b/t/trivial.ll
new file mode 100644
index 0000000..7a9ea57
--- /dev/null
+++ b/t/trivial.ll
@@ -0,0 +1,591 @@
+; ModuleID = 'a'
+source_filename = "../../../t/trivial.pas"
+target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc"
+
+%record = type { i32, [10 x i32], float }
+%record.1 = type { i32, i8, [5 x float], [2 x %record.0] }
+%record.0 = type { [3 x i32], i1 }
+
+@0 = private unnamed_addr constant i1 true
+@1 = private unnamed_addr constant i8 97
+@2 = private unnamed_addr constant i32 5
+@3 = private unnamed_addr constant float 0x400921CAC0000000
+@4 = private unnamed_addr constant [5 x i8] c"nagi\00"
+@5 = private unnamed_addr constant i8* getelementptr inbounds ([5 x i8], [5 x i8]* @4, i32 0, i32 0)
+@6 = private unnamed_addr global i32 0
+@7 = private unnamed_addr global float 0.000000e+00
+@8 = private unnamed_addr global i8* null
+@9 = private unnamed_addr global [5 x i32] zeroinitializer
+@10 = private unnamed_addr constant [12 x i8] c"hello world\00"
+@11 = private unnamed_addr constant [9 x i8] c"testabcd\00"
+@12 = private unnamed_addr constant i1 false
+@13 = private unnamed_addr constant i8 65
+@14 = private unnamed_addr constant i32 10
+@15 = private unnamed_addr constant float 0x4005BF09A0000000
+@16 = private unnamed_addr constant [10 x i8] c"Hanjie Wu\00"
+@17 = private unnamed_addr constant i8* getelementptr inbounds ([10 x i8], [10 x i8]* @16, i32 0, i32 0)
+
+define i32 @arithmetic_test(i32 %0, i8 %1, float %2) {
+arithmetic_test:
+ %3 = alloca i32
+ store i32 %0, i32* %3
+ %4 = alloca i8
+ store i8 %1, i8* %4
+ %5 = alloca float
+ store float %2, float* %5
+ %6 = alloca i32
+ %7 = alloca i8
+ %8 = alloca float
+ %9 = alloca i32
+ store i32 1, i32* %3
+ store i32 -2, i32* %6
+ store i8 66, i8* %4
+ store i8 70, i8* %7
+ store float 1.500000e+00, float* %5
+ store float 0xC0091EB860000000, float* %8
+ %10 = load i32, i32* %3
+ %11 = load i8, i8* %4
+ %12 = sext i8 %11 to i32
+ %13 = add i32 %10, %12
+ %14 = load float, float* %5
+ %15 = sitofp i32 %13 to float
+ %16 = fsub float %15, %14
+ %17 = load i32, i32* %6
+ %18 = sitofp i32 %17 to float
+ %19 = fadd float %16, %18
+ %20 = fptosi float %19 to i32
+ store i32 %20, i32* %3
+ %21 = load i8, i8* %4
+ %22 = load float, float* %5
+ %23 = sitofp i8 %21 to float
+ %24 = fmul float %23, %22
+ %25 = load i32, i32* %6
+ %26 = load i8, i8* %7
+ %27 = sext i8 %26 to i32
+ %28 = mul i32 %25, %27
+ %29 = sitofp i32 %28 to float
+ %30 = fsub float %24, %29
+ %31 = fptosi float %30 to i8
+ store i8 %31, i8* %4
+ %32 = load float, float* %5
+ %33 = load i32, i32* %6
+ %34 = load i8, i8* %7
+ %35 = sext i8 %34 to i32
+ %36 = mul i32 %33, %35
+ %37 = sitofp i32 %36 to float
+ %38 = fadd float %32, %37
+ %39 = load float, float* %8
+ %40 = fadd float %38, %39
+ store float %40, float* %5
+ store i8 1, i8* %4
+ store i8 2, i8* %7
+ %41 = load i8, i8* %4
+ %42 = load i8, i8* %7
+ %43 = sitofp i8 %41 to float
+ %44 = sitofp i8 %42 to float
+ %45 = fdiv float %43, %44
+ %46 = fadd float 5.000000e-01, %45
+ %47 = fptosi float %46 to i32
+ store i32 %47, i32* %3
+ %48 = load i8, i8* %4
+ %49 = load i8, i8* %7
+ %50 = sdiv i8 %48, %49
+ %51 = sext i8 %50 to i32
+ %52 = add i32 0, %51
+ store i32 %52, i32* %6
+ %53 = load i32, i32* %3
+ %54 = load i8, i8* %7
+ %55 = sext i8 %54 to i32
+ %56 = and i32 %53, %55
+ %57 = load i8, i8* %4
+ %58 = load i32, i32* %6
+ %59 = sext i8 %57 to i32
+ %60 = xor i32 %59, %58
+ %61 = or i32 %56, %60
+ store i32 %61, i32* %3
+ %62 = load i32, i32* %3
+ %63 = shl i32 %62, 3
+ %64 = load i32, i32* %3
+ %65 = xor i32 %64, -1
+ %66 = load i8, i8* %4
+ %67 = sext i8 %66 to i32
+ %68 = ashr i32 %65, %67
+ %69 = xor i32 %63, %68
+ store i32 %69, i32* %6
+ %70 = load i32, i32* %3
+ %71 = load i32, i32* %6
+ %72 = add i32 %70, %71
+ store i32 %72, i32* %9
+ %73 = load i32, i32* %9
+ ret i32 %73
+}
+
+define i8 @string_test() {
+string_test:
+ %0 = alloca i8*
+ %1 = alloca i8
+ %2 = alloca i8
+ %3 = alloca i8
+ store i8* getelementptr inbounds ([12 x i8], [12 x i8]* @10, i32 0, i32 0), i8** %0
+ %4 = load i8*, i8** %0
+ %5 = getelementptr inbounds i8, i8* %4, i32 3
+ %6 = load i8, i8* %5
+ store i8 %6, i8* %1
+ %7 = load i8*, i8** %0
+ %8 = getelementptr inbounds i8, i8* %7, i32 6
+ %9 = load i8, i8* %8
+ store i8 %9, i8* %2
+ %10 = load i8, i8* %2
+ %11 = load i8, i8* %1
+ %12 = sub i8 %10, %11
+ %13 = load i8*, i8** %0
+ %14 = sext i8 %12 to i32
+ %15 = getelementptr inbounds i8, i8* %13, i32 %14
+ %16 = load i8, i8* %15
+ store i8 %16, i8* %3
+ %17 = load i8, i8* %3
+ ret i8 %17
+}
+
+define i32 @array_test() {
+array_test:
+ %0 = alloca [26 x i32]
+ %1 = alloca [26 x i8]
+ %2 = alloca i32
+ %3 = alloca i8
+ %4 = alloca i32
+ store i32 0, i32* %2
+ store i8 122, i8* %3
+ br label %loop
+
+loop: ; preds = %check, %array_test
+ %5 = load i32, i32* %2
+ %6 = getelementptr inbounds [26 x i8], [26 x i8]* %1, i32 0, i32 %5
+ %7 = load i8, i8* %3
+ store i8 %7, i8* %6
+ %8 = load i8, i8* %3
+ %9 = sub i8 %8, 97
+ %10 = getelementptr inbounds [26 x i32], [26 x i32]* %0, i32 0, i8 %9
+ %11 = load i32, i32* %2
+ store i32 %11, i32* %10
+ %12 = load i32, i32* %2
+ %13 = add i32 %12, 1
+ store i32 %13, i32* %2
+ %14 = load i8, i8* %3
+ %15 = sext i8 %14 to i32
+ %16 = sub i32 %15, 1
+ %17 = trunc i32 %16 to i8
+ store i8 %17, i8* %3
+ br label %check
+
+check: ; preds = %loop
+ %18 = load i32, i32* %2
+ %19 = icmp sgt i32 %18, 25
+ br i1 %19, label %done, label %loop
+
+done: ; preds = %check
+ %20 = getelementptr inbounds [26 x i32], [26 x i32]* %0, i32 0, i8 5
+ %21 = load i32, i32* %20
+ %22 = getelementptr inbounds [26 x i8], [26 x i8]* %1, i32 0, i32 5
+ %23 = load i8, i8* %22
+ %24 = sext i8 %23 to i32
+ %25 = sub i32 %21, %24
+ store i32 %25, i32* %4
+ %26 = load i32, i32* %4
+ ret i32 %26
+}
+
+define i32 @pointer_test() {
+pointer_test:
+ %0 = alloca i32
+ %1 = alloca i32
+ %2 = alloca [101 x i32]
+ %3 = alloca i32*
+ %4 = alloca i32*
+ %5 = alloca i8*
+ %6 = alloca i8*
+ %7 = alloca i32
+ store i32 1, i32* %0
+ %8 = getelementptr inbounds [101 x i32], [101 x i32]* %2, i32 0, i32 0
+ store i32* %8, i32** %3
+ %9 = getelementptr inbounds [101 x i32], [101 x i32]* %2, i32 0, i32 4
+ store i32* %9, i32** %4
+ %10 = load i32*, i32** %4
+ %11 = load i32*, i32** %3
+ %12 = ptrtoint i32* %10 to i32
+ %13 = ptrtoint i32* %11 to i32
+ %14 = sub i32 %12, %13
+ store i32 %14, i32* %1
+ %15 = load i32*, i32** %3
+ %16 = getelementptr inbounds i32, i32* %15, i32 0
+ %17 = load i32, i32* %0
+ store i32 %17, i32* %16
+ %18 = load i32, i32* %1
+ %19 = load i32*, i32** %4
+ %20 = getelementptr inbounds i32, i32* %19, i32 %18
+ %21 = load i32, i32* %0
+ store i32 %21, i32* %20
+ %22 = load i32*, i32** %3
+ %23 = getelementptr inbounds i32, i32* %22, i32 1
+ %24 = getelementptr inbounds i32, i32* %23, i32 0
+ %25 = load i32, i32* %0
+ %26 = add i32 %25, 1
+ store i32 %26, i32* %24
+ %27 = load i32*, i32** %3
+ %28 = getelementptr inbounds i32, i32* %27, i32 0
+ %29 = load i32, i32* %28
+ %30 = load i32*, i32** %3
+ %31 = getelementptr inbounds i32, i32* %30, i32 1
+ %32 = load i32, i32* %31
+ %33 = add i32 %29, %32
+ store i32 %33, i32* %1
+ store i8* getelementptr inbounds ([9 x i8], [9 x i8]* @11, i32 0, i32 0), i8** %5
+ %34 = load i8*, i8** %5
+ %35 = getelementptr inbounds i8, i8* %34, i32 2
+ store i8* %35, i8** %6
+ %36 = load i32, i32* %1
+ %37 = load i8*, i8** %6
+ %38 = getelementptr inbounds i8, i8* %37, i32 3
+ %39 = load i8, i8* %38
+ %40 = sext i8 %39 to i32
+ %41 = add i32 %36, %40
+ store i32 %41, i32* %7
+ %42 = load i32, i32* %7
+ ret i32 %42
+}
+
+define i32 @recursion_test(i32 %0) {
+recursion_test:
+ %1 = alloca i32
+ store i32 %0, i32* %1
+ %2 = alloca i32
+ %3 = load i32, i32* %1
+ %4 = icmp eq i32 %3, 0
+ %5 = load i32, i32* %1
+ %6 = icmp eq i32 %5, 1
+ %7 = or i1 %4, %6
+ br i1 %7, label %then, label %else
+
+then: ; preds = %recursion_test
+ store i32 1, i32* %2
+ br label %endif
+
+else: ; preds = %recursion_test
+ %8 = load i32, i32* %1
+ %9 = sub i32 %8, 1
+ %10 = call i32 @recursion_test(i32 %9)
+ %11 = load i32, i32* %1
+ %12 = sub i32 %11, 2
+ %13 = call i32 @recursion_test(i32 %12)
+ %14 = add i32 %10, %13
+ store i32 %14, i32* %2
+ br label %endif
+
+endif: ; preds = %else, %then
+ %15 = load i32, i32* %2
+ ret i32 %15
+}
+
+define i32 @branch_test(i32 %0) {
+branch_test:
+ %1 = alloca i32
+ store i32 %0, i32* %1
+ %2 = alloca i32
+ %3 = alloca i32
+ %4 = alloca i32
+ %5 = alloca i32
+ store i32 3, i32* %2
+ store i32 0, i32* %3
+ store i32 4, i32* %4
+ %6 = load i32, i32* %1
+ %7 = load i32, i32* %2
+ %8 = icmp slt i32 %6, %7
+ br i1 %8, label %then, label %else
+
+then: ; preds = %branch_test
+ store i32 -1, i32* %3
+ br label %endif2
+
+else: ; preds = %branch_test
+ %9 = load i32, i32* %1
+ %10 = load i32, i32* %2
+ %11 = icmp sgt i32 %9, %10
+ br i1 %11, label %then1, label %endif
+
+then1: ; preds = %else
+ store i32 1, i32* %3
+ br label %endif
+
+endif: ; preds = %then1, %else
+ br label %endif2
+
+endif2: ; preds = %endif, %then
+ br label %start
+
+start: ; preds = %done, %endif2
+ %12 = load i32, i32* %2
+ %13 = icmp sgt i32 %12, 0
+ br i1 %13, label %loop, label %done7
+
+loop: ; preds = %start
+ br label %start3
+
+start3: ; preds = %endif6, %loop
+ %14 = load i32, i32* %4
+ %15 = icmp sgt i32 %14, 0
+ br i1 %15, label %loop4, label %done
+
+loop4: ; preds = %start3
+ %16 = load i32, i32* %4
+ %17 = sub i32 %16, 1
+ store i32 %17, i32* %4
+ %18 = load i32, i32* %4
+ %19 = icmp eq i32 %18, 3
+ br i1 %19, label %then5, label %endif6
+
+then5: ; preds = %loop4
+ store i32 2, i32* %4
+ br label %done
+
+endif6: ; preds = %loop4
+ %20 = load i32, i32* %1
+ %21 = load i32, i32* %4
+ %22 = mul i32 %20, %21
+ %23 = load i32, i32* %2
+ %24 = add i32 %22, %23
+ store i32 %24, i32* %1
+ br label %start3
+
+done: ; preds = %then5, %start3
+ %25 = load i32, i32* %2
+ %26 = sub i32 %25, 1
+ store i32 %26, i32* %2
+ br label %start
+
+done7: ; preds = %start
+ br label %loop8
+
+loop8: ; preds = %check13, %done7
+ br label %loop9
+
+loop9: ; preds = %check, %loop8
+ %27 = load i32, i32* %4
+ %28 = add i32 %27, 1
+ store i32 %28, i32* %4
+ %29 = load i32, i32* %4
+ %30 = icmp eq i32 %29, 3
+ br i1 %30, label %then10, label %endif11
+
+then10: ; preds = %loop9
+ store i32 4, i32* %4
+ br label %check
+
+endif11: ; preds = %loop9
+ %31 = load i32, i32* %1
+ %32 = load i32, i32* %3
+ %33 = mul i32 %31, %32
+ %34 = load i32, i32* %4
+ %35 = add i32 %33, %34
+ store i32 %35, i32* %1
+ br label %check
+
+check: ; preds = %endif11, %then10
+ %36 = load i32, i32* %4
+ %37 = icmp sgt i32 %36, 5
+ br i1 %37, label %done12, label %loop9
+
+done12: ; preds = %check
+ %38 = load i32, i32* %1
+ %39 = load i32, i32* %3
+ %40 = mul i32 %38, %39
+ store i32 %40, i32* %1
+ %41 = load i32, i32* %2
+ %42 = add i32 %41, 1
+ store i32 %42, i32* %2
+ br label %check13
+
+check13: ; preds = %done12
+ %43 = load i32, i32* %2
+ %44 = icmp sgt i32 %43, 5
+ br i1 %44, label %done14, label %loop8
+
+done14: ; preds = %check13
+ %45 = load i32, i32* %1
+ store i32 %45, i32* %5
+ %46 = load i32, i32* %5
+ ret i32 %46
+}
+
+define i32 @name_test_global() {
+name_test_global:
+ %0 = alloca i32
+ store i32 1, i32* @6
+ %1 = load i32, i32* @6
+ %2 = load i1, i1* @0
+ %3 = sext i1 %2 to i32
+ %4 = add i32 %1, %3
+ %5 = load i8, i8* @1
+ %6 = sext i8 %5 to i32
+ %7 = add i32 %4, %6
+ %8 = load i32, i32* @2
+ %9 = add i32 %7, %8
+ %10 = load float, float* @3
+ %11 = sitofp i32 %9 to float
+ %12 = fadd float %11, %10
+ %13 = load i8*, i8** @5
+ %14 = getelementptr inbounds i8, i8* %13, i32 3
+ %15 = load i8, i8* %14
+ %16 = sitofp i8 %15 to float
+ %17 = fadd float %12, %16
+ %18 = fptosi float %17 to i32
+ store i32 %18, i32* %0
+ %19 = load i32, i32* %0
+ ret i32 %19
+}
+
+define i32 @name_test_local() {
+name_test_local:
+ %0 = alloca i32
+ %1 = alloca i32
+ store i32 0, i32* %0
+ %2 = load i32, i32* %0
+ %3 = load i1, i1* @12
+ %4 = sext i1 %3 to i32
+ %5 = add i32 %2, %4
+ %6 = load i8, i8* @13
+ %7 = sext i8 %6 to i32
+ %8 = add i32 %5, %7
+ %9 = load i32, i32* @14
+ %10 = add i32 %8, %9
+ %11 = load float, float* @15
+ %12 = sitofp i32 %10 to float
+ %13 = fadd float %12, %11
+ %14 = load i8*, i8** @17
+ %15 = getelementptr inbounds i8, i8* %14, i32 3
+ %16 = load i8, i8* %15
+ %17 = sitofp i8 %16 to float
+ %18 = fadd float %13, %17
+ %19 = fptosi float %18 to i32
+ store i32 %19, i32* %1
+ %20 = load i32, i32* %1
+ ret i32 %20
+}
+
+define i1 @name_test() {
+name_test:
+ %0 = alloca i1
+ %1 = call i32 @name_test_global()
+ %2 = call i32 @name_test_local()
+ %3 = icmp ne i32 %1, %2
+ store i1 %3, i1* %0
+ %4 = load i1, i1* %0
+ ret i1 %4
+}
+
+define void @void_test() {
+void_test:
+ %0 = alloca i8*
+ %1 = alloca i8*
+ ret void
+}
+
+define i32 @alias_test() {
+alias_test:
+ %0 = alloca i32
+ %1 = alloca [10 x [10 x i32]]
+ %2 = alloca [10 x i32]*
+ %3 = alloca [10 x [100 x [10 x i32]]]
+ %4 = alloca %record
+ %5 = alloca i32
+ store i32 4, i32* %0
+ %6 = load i32, i32* %0
+ %7 = getelementptr inbounds [10 x [10 x i32]], [10 x [10 x i32]]* %1, i32 0, i32 %6
+ %8 = load i32, i32* %0
+ %9 = getelementptr inbounds [10 x i32], [10 x i32]* %7, i32 0, i32 %8
+ %10 = load i32, i32* %0
+ store i32 %10, i32* %9
+ %11 = load i32, i32* %0
+ %12 = getelementptr inbounds [10 x [10 x i32]], [10 x [10 x i32]]* %1, i32 0, i32 %11
+ store [10 x i32]* %12, [10 x i32]** %2
+ %13 = load [10 x i32]*, [10 x i32]** %2
+ %14 = getelementptr inbounds [10 x i32], [10 x i32]* %13, i32 0
+ %15 = load i32, i32* %0
+ %16 = getelementptr inbounds [10 x i32], [10 x i32]* %14, i32 0, i32 %15
+ %17 = load [10 x i32]*, [10 x i32]** %2
+ %18 = getelementptr inbounds [10 x i32], [10 x i32]* %17, i32 0
+ %19 = load i32, i32* %0
+ %20 = getelementptr inbounds [10 x i32], [10 x i32]* %18, i32 0, i32 %19
+ %21 = load i32, i32* %20
+ %22 = add i32 %21, 1
+ store i32 %22, i32* %16
+ %23 = getelementptr inbounds [10 x [100 x [10 x i32]]], [10 x [100 x [10 x i32]]]* %3, i32 0, i32 0
+ %24 = getelementptr inbounds [100 x [10 x i32]], [100 x [10 x i32]]* %23, i32 0, i32 1
+ %25 = getelementptr inbounds [10 x i32], [10 x i32]* %24, i32 0, i32 2
+ store i32 123, i32* %25
+ %26 = getelementptr inbounds [10 x [100 x [10 x i32]]], [10 x [100 x [10 x i32]]]* %3, i32 0, i32 0
+ %27 = getelementptr inbounds [100 x [10 x i32]], [100 x [10 x i32]]* %26, i32 0, i32 1
+ %28 = getelementptr inbounds [10 x i32], [10 x i32]* %27, i32 0, i32 2
+ %29 = load i32, i32* %28
+ %30 = load i32, i32* %0
+ %31 = getelementptr inbounds [10 x [10 x i32]], [10 x [10 x i32]]* %1, i32 0, i32 %30
+ %32 = load i32, i32* %0
+ %33 = getelementptr inbounds [10 x i32], [10 x i32]* %31, i32 0, i32 %32
+ %34 = load i32, i32* %33
+ %35 = load i32, i32* %0
+ %36 = mul i32 %34, %35
+ %37 = add i32 %29, %36
+ store i32 %37, i32* %5
+ %38 = load i32, i32* %5
+ ret i32 %38
+}
+
+define i32 @record_test() {
+record_test:
+ %0 = alloca %record.1
+ %1 = alloca %record.1*
+ %2 = alloca i32
+ %3 = getelementptr inbounds %record.1, %record.1* %0, i32 0, i32 0
+ store i32 2, i32* %3
+ %4 = getelementptr inbounds %record.1, %record.1* %0, i32 0, i32 1
+ store i8 116, i8* %4
+ %5 = getelementptr inbounds %record.1, %record.1* %0, i32 0, i32 2
+ %6 = getelementptr inbounds [5 x float], [5 x float]* %5, i32 0, i32 0
+ store float 0x401AA3D700000000, float* %6
+ store %record.1* %0, %record.1** %1
+ %7 = load %record.1*, %record.1** %1
+ %8 = getelementptr inbounds %record.1, %record.1* %7, i32 0
+ %9 = getelementptr inbounds %record.1, %record.1* %8, i32 0, i32 2
+ %10 = getelementptr inbounds [5 x float], [5 x float]* %9, i32 0, i32 4
+ store float 0x401F147AE0000000, float* %10
+ %11 = load %record.1*, %record.1** %1
+ %12 = getelementptr inbounds %record.1, %record.1* %11, i32 0
+ %13 = getelementptr inbounds %record.1, %record.1* %12, i32 0, i32 3
+ %14 = getelementptr inbounds [2 x %record.0], [2 x %record.0]* %13, i32 0, i32 0
+ %15 = getelementptr inbounds %record.0, %record.0* %14, i32 0, i32 0
+ %16 = getelementptr inbounds [3 x i32], [3 x i32]* %15, i32 0, i32 2
+ store i32 1234, i32* %16
+ %17 = getelementptr inbounds %record.1, %record.1* %0, i32 0, i32 2
+ %18 = getelementptr inbounds [5 x float], [5 x float]* %17, i32 0, i32 4
+ %19 = load float, float* %18
+ %20 = load %record.1*, %record.1** %1
+ %21 = getelementptr inbounds %record.1, %record.1* %20, i32 0
+ %22 = getelementptr inbounds %record.1, %record.1* %21, i32 0, i32 2
+ %23 = getelementptr inbounds %record.1, %record.1* %0, i32 0, i32 0
+ %24 = load i32, i32* %23
+ %25 = sub i32 %24, 2
+ %26 = getelementptr inbounds [5 x float], [5 x float]* %22, i32 0, i32 %25
+ %27 = load float, float* %26
+ %28 = fadd float %19, %27
+ %29 = getelementptr inbounds %record.1, %record.1* %0, i32 0, i32 3
+ %30 = getelementptr inbounds [2 x %record.0], [2 x %record.0]* %29, i32 0, i32 0
+ %31 = getelementptr inbounds %record.0, %record.0* %30, i32 0, i32 0
+ %32 = getelementptr inbounds [3 x i32], [3 x i32]* %31, i32 0, i32 2
+ %33 = load i32, i32* %32
+ %34 = sitofp i32 %33 to float
+ %35 = fadd float %28, %34
+ %36 = fptosi float %35 to i32
+ store i32 %36, i32* %2
+ %37 = load i32, i32* %2
+ ret i32 %37
+}