Skip to content

Instantly share code, notes, and snippets.


sheijk/Makefile Secret

Created Sep 22, 2014
What would you like to do?
// Small repro case to test how ParseAssemblyString will resolve references to
// types that are already defined in the module.
// If the parsed code uses a type foo_t that has been defined before in the
// module the parser will create a new opaque type foo_t.0 and use that
// instead. In contrast if foo_t gets defined inside the parsed code it will be
// used. (note: defining foo_t using the StructType::create has the same result
// as defining it using the parser).
// Change the variable `together' to true to see how the parser behaves when the
// type is defined at the same time as the code using it.
// I guess this change has been introduced during the changes to the type system
// in 3.0. Is there a way to use a type that has already been defined in the
// module before from code passed to ParseAssemblyString?
// #include "llvm/Analysis/Verifier.h"
#include "llvm/AsmParser/Parser.h"
#include "llvm/ExecutionEngine/GenericValue.h"
#include "llvm/ExecutionEngine/Interpreter.h"
#include "llvm/ExecutionEngine/JIT.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/raw_ostream.h"
#include <memory>
using namespace llvm;
/* Output with no args
---- Module after type:
; ModuleID = 'test'
%struct.foo_t = type { i32 }
declare void @dummy(%struct.foo_t)
---- module end
<string>:1:19: LLVM error: use of undefined type named 'struct.foo_t'
---- Module after func:
; ModuleID = 'test'
%struct.foo_t = type { i32 }
%struct.foo_t.0 = type opaque
declare void @dummy(%struct.foo_t)
declare void @func(%struct.foo_t.0*)
---- module end
/* Output with --combined
---- Module after type+func:
; ModuleID = 'test'
%struct.foo_t = type { i32 }
declare void @dummy(%struct.foo_t)
declare void @func(%struct.foo_t*)
---- module end
void ParseAndReport(LLVMContext& Context, Module& M, const char* action, const char* source) {
SMDiagnostic ErrorInfo;
Module *ParsedModule = ParseAssemblyString( source, &M, ErrorInfo, Context );
if( !ErrorInfo.getMessage().empty() ) {
int line = ErrorInfo.getLineNo();
fprintf( stderr, "%s:%d:%d: LLVM error: %s\n",
ErrorInfo.getMessage().data() );
errs() << "---- Module after " << action << ":\n" << M << "\n---- module end\n";
int main(int argc, char **argv) {
bool combined = false;
if (argc <= 1) {
combined = false;
else if (argc == 2 && (argv[1] == std::string("--combined"))) {
combined = true;
else {
fprintf(stderr, "error: expected no args or --combined\n");
LLVMContext Context;
// Create some module to put our function into it.
std::auto_ptr<Module> M(new Module("test", Context));
// the dummy declaration is needed to keep the parser from omitting struct.foo_t
const char* CodeWithType =
"%struct.foo_t = type { i32 }\n"
"declare void @dummy(%struct.foo_t %p)\n";
const char* CodeWithFunc = "declare void @func(%struct.foo_t* %ptr)\n";
if(combined) {
std::string source = std::string(CodeWithType) + CodeWithFunc;
ParseAndReport(Context, *M.get(), "type+func", source.c_str());
else {
ParseAndReport(Context, *M.get(), "type", CodeWithType);
ParseAndReport(Context, *M.get(), "func", CodeWithFunc);
return 0;
CXXFLAGS += -I $(LLVM_DIR)include
CXXFLAGS += $(shell $(LLVM_BIN_DIR)llvm-config --cxxflags)
llvm-parse: llvm-parse.o
$(CXX) $(shell $(LLVM_BIN_DIR)llvm-config --ldflags) $(shell $(LLVM_BIN_DIR)llvm-config --libs jit interpreter asmparser nativecodegen) -lz -lcurses $< -o $@
llvm-parse.o: llvm-parse.cpp
$(CXX) -c $(CXXFLAGS) $< -o $@
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment