Giter VIP home page Giter VIP logo

cplus's Introduction

made-with-C++ GitHub issues GitHub pull-requests License

Сplus

Compiler for C+ toy imperative language, based on LLVM.

Getting started

  • Code sample.cp

    routine main() is
        println "Hello C+";
        return;
    end
  • Compile

    $ ./cplus sample.cp
    
    Compilation successful. Run ./a.out to execute
  • Run

    $ ./a.out
    Hello C+
  • Generated ir.ll

    ; ModuleID = 'ir.ll'
    source_filename = "ir.ll"
    target triple = "x86_64-pc-linux-gnu"
    
    @fmt_s_ln = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1
    @str = private unnamed_addr constant [9 x i8] c"Hello C+\00", align 1
    
    define i64 @main() {
    entry:
      %printfCall = call i64 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @fmt_s_ln, i32 0, i32 0), i8* getelementptr inbounds ([9 x i8], [9 x i8]* @str, i32 0, i32 0))
      ret i64 0
    }
    
    declare i64 @printf(i8*, ...)
  • Debug output from cplus -d sample.cp

    debug

Compilation from source (Linux)

  1. Install prerequisites: cmake flex bison clang llvm-10 using the package manager for your distro.

    • Example (Ubuntu 20.04 LTS): sudo apt install cmake flex bison clang llvm
  2. Clone repo

    git clone https://github.com/Sh3B0/cplus/
    cd cplus
  3. Build cplus binary using CMake

    mkdir build
    cmake -S . -B build
    cmake --build build
  4. Compile a source file *.cp (check tests)

    cd build
    ./cplus -d ../tests/1.cp
  5. Help

    $ ./cplus --help
    usage: cplus [options] infile
    	infile                 path to the source code file (*.cp) to compile.
    
    options:
    	-h, --help             show this help message and exit.
    	-d, --debug            show debug messages.
    	-o, --outfile outfile  specify executable file name.

Contribution

Feel free to report a bug or suggest a feature by creating an issue.

License

The source code is licensed under the MIT license, which you can find in the LICENSE file.

cplus's People

Contributors

goar5670 avatar sh1co avatar sh3b0 avatar tonydecva180xn avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Forkers

goar5670 sh1co

cplus's Issues

Memory checks for arrays

Example code

routine main() is
	var x : array[5] integer;
	x[-1] := -1;
	x[0] := 0;
	x[6] := 6;
	println x[-1];
	println x[0];
	println x[6];
	return;
end

Expected behavor

Runtime errors as we access invalid indexes (btw, C+ arrays are 1-indexed)

Actual behavior

Prints -1, 0, 6
Although seems cool, it shouldn't be like this.

Return statements inside basic blocks

Code to reproduce

routine power(number : integer, to_power : integer) : integer is
	var tmp is 1;
	if to_power < 1 then
		return 1;
	end
	for i in 0 .. to_power - 1 loop
		tmp := tmp * number;
	end
	return tmp;
end

routine main(input : integer) is 
	println power(2, 3);
	return;
end

Expected behavior

Prints 8

Actual behavior

[LLVM]: [WARNINGS]:
Terminator found in the middle of a basic block!
label %then

ir.ll:38:3: error: instruction expected to be numbered '%1'
  %0 = load i64, i64* %tmp
  ^
1 error generated.
Error generating IR

Comments

  • Return statements inside basic basic blocks (if/else label, for loop) always produce that warning, sometimes the program still work, but it's better to invistigate that issue as it might be the root cause.
  • Related question

Enhancements checklist

  • Add support for multidimensioan arrays and arrays of records.
  • Add support for recursive routines.
  • Allow using arrays/records as global variables and routine arguments.
  • Generate fmt consts as needed and remove is_first_routine hack.
  • Visiting identifier should only assign to tmp_p, loading into tmp_v should be done in AssignmentStatement only (this will make the IR much shorter).
  • Add support for Windows.

Argv input doesn't work

Code to reproduce

routine main(x: integer) : integer is
	println x;
	return 0;
end
$ ./cplus -d source.cp
$ ./a.out 5

Expected output

Prints 5

Actual output

Prints other random value, although the generated ir.ll seems correct.

Initializing a variable with record/array element

Code to reproduce

routine main() is
	var x : array[5] integer;
	x[1] := 1;
	var y is x[1];
	println y;
	return;
end

Expected behavior

Prints 1

Actual behavior

Prints garbage from memory, most probably the error originates from the local variable intialization code in VariableDeclarartion::visit

Issues with implicit casting

Code to reproduce

routine main() is
	var x : integer is 1.1;
	println x;
	return;
end

Expected behavior

Prints 1 as x is casted from real to integer.

Actual behavior

Prints 1.1, x is declared with real dtype as the code deduces dtype from iv disregarding user explicit type specification.
Can be fixed by modifying the visit method for VariableDeclaration to use casting as it's already done in AssignmentStatement.

Notes

  • Separate declaration then assignment does behave correctly.
  • Same problem happens with global variables, can be fixed in the same manner.
  • With routine calls and routine return statements, casting should also be implemented.

Assigning new values to arguments

Code to reproduce

routine modify(x : integer) is
    x := 2;
    println x;
    return;
end

routine main() is
    modify(5);
    return;
end

Expected behavior

Prints 2

Actual behavior

[AST]:
<Program>
|   <RoutineDeclaration>
|   |   <Body>
|   |   |   <AssignmentStatement>
|   |   |   |   <Identifier>
|   |   |   |   </Identifier>
cplus: /usr/lib/llvm-10/include/llvm/IR/Type.h:382: llvm::Type* llvm::Type::getPointerElementType() const: Assertion `getTypeID() == PointerTyID' failed.
./run.sh: line 5: 73279 Aborted                 (core dumped) ./build/cplus -d examples/sample.cp

Notes

  • This happens because the assignment statement tries to access the location of x by visiting the identifier node, which assigns to tmp_v rather than tmp_p in cast of argument (from args_table)
  • One way to solve this would be to make args_table return pointers instead of values (like ptrs_table), but this would require modifications in RoutineDeclarations.
  • We may actually use only one table (ptrs_table) and remove (args_table)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.